New Year Book Reading E

题面:

New Year Book Reading E

题目大意:

小明打算在假期读书,他有n本书,第i本书有重量wi,给出小明读书的顺序,求怎么摆放一开始的书,使得小明读完书后,累计搬起的重量为最小值,并输出。
有以下规则:

  1. 当小明要拿一本书时,他要举起的重量是这本书上面的全部书的重量。
  2. 当小明看完一本书的时候,他会把书放在所有书的最上面。

思路:

一开始看这题是有点蒙的,但是你拿样例来模拟一下,就能发现,这其实也是有一点规律的。

首先我们划出一个分界线,上面是空的,下面是所有的书(不用理会顺序),然后我们拿第一本的时候,肯定它如果在下面的第一个重量是最少的,拿第二本时,如果它在分界线下面,那么它是分界线下面的第一本的话,需要抬起的重量是分界线上面的书,也就是重量最少的选择,如果在上面的话,因为上面顺序已经定了,所以直接模拟拿书过程就行,那么可以知道,一开始书的顺序其实是这本书第一次出现的顺序,比如
1 3 1 2 2 3 1最先出现的顺序是1->3->2,可以开个vis标记一下,其他的过程模拟拿书过程就行。
代码如下:


#include <iostream>
#include <cstdio>
#include<cstring>
using namespace std;
#define MAX 505
struct Node{
	int w;
	int i;
}x[MAX];
int vis[MAX];
int n,m;
int w[MAX];
long long ans;
int main()
{
	scanf("%d %d",&n,&m);
	for(int i = 1;i<=n;i++)
	{
		scanf("%d",&w[i]);
	}
	int sum = 0,k = 0;
	for(int i = 0;i<m;i++)
	{
		int temp;
		scanf("%d",&temp);
		if(vis[temp])
		{
			Node a;
			for(int j = 0;j<k;j++)
			{

				if(x[j].i == temp)
				{
					a = x[j];
					while(j<k-1)
					{
						x[j] = x[j+1];
						ans+=x[j].w;
						j++;
					}
				}
			}
			x[k-1] = a;
		}
		else
		{
			ans+=sum;
			vis[temp] = 1;
			x[k].w = w[temp];
			x[k].i = temp;
			sum+=w[temp];
			k++;

		}
	}
	printf("%lld",ans);
	return 0;
}