UVALive 5902 - Movie collection(BIT)
题目链接 https://cn.vjudge.net/problem/UVALive-5902
【题意】
给你一个长度为n的序列,刚开始序列从前到后分别为1,2,3…n,之后有若干次如下操作
每次选中一个元素x,统计序列中在x前面的元素有多少个,然后把x放到第一位
【输入格式】
多组输入,第一行为数据组数T. 之后每组数据第一行有两个整数n,m(n,m<=1e5)代表序列长度和操作次数,下一行有m个1~n之间的整数代表每次要对那个元素进行操作
【输出格式】
对每组数据,输出每次操作中排在当前元素前面的元素有多少个,用空格隔开
【思路】
BIT的简单应用,首先可以把元素的位置向右做一个偏移,然后用一个pos数组记录每个元素所处的位置,对应位置的BIT下标置为1,然后每次操作时,取出一个元素x,那么它前面的元素个数就是sum(pos[x]-1),之后就把x处的值重新赋值为0,在最前面找一处位置放入x同时更新pos数组即可
#include<bits/stdc++.h>
using namespace std;
const int maxn=200050;
const int pian=100005;
int n,m;
int bit[maxn],len;
int pos[maxn];
void add(int i,int x){
while(i<=len){
bit[i]+=x;
i+=i&-i;
}
}
int sum(int i){
int ans=0;
while(i){
ans+=bit[i];
i-=i&-i;
}
return ans;
}
int main(){
int T;
scanf("%d",&T);
while(T--){
scanf("%d%d",&n,&m);
len=n+pian;
memset(bit,0,sizeof(bit));
for(int i=1;i<=n;++i){
pos[i]=i+pian;
add(pos[i],1);
}
int cur=pian;
for(int i=1;i<=m;++i){
int x;
scanf("%d",&x);
printf("%d%c",sum(pos[x]-1),i==m?'\n':' ');
add(pos[x],-1);
pos[x]=cur--;
add(pos[x],1);
}
}
return 0;
}