题目链接:codeforces 500C


这个题,不是难在写代码,而是难在了如何去证明这个结论(其实猜想也是只要胆子大,就是可以过的)

关键是从样例中找到这个题的解法!


书的初始排列顺序是定好的!

就是按照m本书的给定数据,从前到后,建立一个链表,然后去暴力操作就好!


证明是所谓的理论证明吧,就是读的书是需要把该书上面的书全部拿走的。那么,越早阅读的书,放在越上面越好咯


那么,涉及到最重要的问题

数据结构是个链表:在暴力找到了需要读的书之后,需要把这个节点删除,然后插入到起点和起点的后一个点之中

然后就是个看基本功的题了


#include<bits/stdc++.h>
using namespace std;

const int maxn=550;
const int maxm=1050;
struct node{
	int L,R;
}a[maxn];
int c[maxn],x[maxm];
int mp[maxm],n,m,ans,tot;
bool vis[maxm];
int Head,Tail;

void debug(){
	//GetRight
	int pos=Head;
	while(pos!=Tail){
		pos=a[pos].R;
		//cout<<c[pos]<<endl;
		cout<<pos<<" ";
	}
	cout<<endl;
	pos=Tail;
	while(pos!=Head){
		pos=a[pos].L;
		//cout<<pos<<endl;
		cout<<pos<<" ";
	}
	cout<<endl;
	cout<<endl;
}

int main(){
	//freopen("input1.txt","r",stdin);
	while(scanf("%d%d",&n,&m)!=EOF){
		c[0]=0;
		c[n+1]=0;
		for(int i=1;i<=n;i++) scanf("%d",&c[i]);
		memset(vis,false,sizeof(vis));
		ans=tot=0;
		for(int i=1;i<=m;i++){
			scanf("%d",&x[i]);
			if (!vis[x[i]]){
				vis[x[i]]=true;
				mp[++tot]=x[i];
			}
		}
		memset(a,-1,sizeof(a));
		Head=0;
		Tail=n+1;
		a[Head].R=mp[1];
		a[Tail].L=mp[tot];
		for(int i=1;i<=tot;i++)
			if (i==1){
				a[mp[i]].L=Head;
				a[mp[i]].R=mp[i+1];
			}
			else if (i==n){
				a[mp[i]].R=Tail;
				a[mp[i]].L=mp[i-1];
			}
			else{
				a[mp[i]].L=mp[i-1];
				a[mp[i]].R=mp[i+1];
			}
		for(int i=1;i<=m;i++){
			int pos=Head,temp=0;
			while(pos!=x[i]){
				temp+=c[pos];
				pos=a[pos].R;
				//cout<<pos<<" ";
			}
			//cout<<temp<<endl;
			//debug();
			ans+=temp;
			a[a[pos].L].R=a[pos].R;
			a[a[pos].R].L=a[pos].L;
			a[pos].R=a[Head].R;
			a[pos].L=Head;
			a[a[Head].R].L=pos;
			a[Head].R=pos;
		}
		printf("%d\n",ans);
	}
	return 0;
}