题目描述 :
柯南准备去读n本书,标号为1~n,每本书的重量为wi.柯南家太小啦,没办法放下一个书橱,于是就只好将这些书堆成一个垂直的堆,他现在想要读第x本书,他要这么做。
1.举起在x上面的所有的书
2.然后将x书从堆里面拿出来
3.将x上面的书不改变顺序地放回去
4.将x放到最上面
他决定在m天内读书,在第j天,他会读第bj (1 ≤ bj ≤ n)本书. 他取出书的方式就如同上面说的那样。
做了这样的计划之后,他突然发现作为一个一年级学生他举起想读的书上的书实在是太重了。所以他决定改变书堆的顺序(也就是初始的书是怎么堆的),从而减少总归抬起书的重量。
注意:他将x书抽出来的时候不算进抬起的重量。
输入描述 :
给你两个整数 n (2 ≤ n ≤ 500) 和 m (1 ≤ m ≤ 1000) — 书的个数和读书的天数接下来一行有n个整数表示 w1, w2, ..., wn (1 ≤ wi ≤ 100) — 书的重量。第三行有m个整数表示每一天看什么书 b1, b2, ..., bm (1 ≤ bj ≤ n) Note that he can read the same book more than once.
输出描述 :
他将书堆里面的书重新排列之后最少要举起多少重量呢?
样列 :
3 5 1 2 3 1 3 2 3 1
12
题解 :
队列模拟,不过需要注意的是不一定是从尾部插入队列,好比:要看第 bj 本书,要把 1---bj-1 本书插到第 bj+1 本书之前,第 bj 本书放在首位。
#include<stdio.h>
#include<queue>
#include<set>
#include<algorithm>
using namespace std;
set<int>ss;queue<int >qq;
int main(){
int n,m,k;
int a[505];
int b[1005];
int c[1005];
while(!qq.empty()){
qq.pop();
}
ss.clear();
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
}
for(int i=0;i<m;i++){
scanf("%d",&b[i]);
if(!ss.count(b[i])){
ss.insert(b[i]);
qq.push(b[i]);
}
}
int sum=0;
for(int i=0;i<m;i++){
int p=1;
while(!qq.empty()){
int d=qq.front();
if(d==b[i]){
c[0]=d;
qq.pop();
break;
}
else{
sum+=a[d];
// printf("%d\n",a[d]);
c[p++]=d;
qq.pop();
//qq.push(d);
}
}
while(!qq.empty()){
c[p++]=qq.front();
qq.pop();
}
for(int l=0;l<p;l++){
qq.push(c[l]);
}
}
printf("%d\n",sum);
return 0;
}