题目:http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=27885
题意:有n个物品从上到下放置,并且标号1~n,有n次查询,每次查询标号为x的物品现在的位置(0~n,即该物品上面有多少个物品),同时将该物品取出放到第0号位置。
分析:将1~n件物品重新编号,1~n标为n~1,每次拿出一件物品x,再将其重新编号,如果是第一次拿出就标为n+1.....依次递增,然后将之前的编号删掉,插入新的编号。
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
using namespace std;
const int maxn = 2e5+6;
int tree[maxn],lowbit[maxn],num[maxn];
void getlowbit()
{
for(int i=1;i<maxn;i++)
lowbit[i]=i&-i;
}
void update(int x,int v)
{
for(int i=x;i<maxn;i+=lowbit[i])
tree[i]+=v;
}
int query(int x)
{
int ret(0);
for(int i=x;i>0;i-=lowbit[i])
ret+=tree[i];
return ret;
}
int main()
{
getlowbit();
int ncase,n,i,j,q,cur,x;
scanf("%d",&ncase);
while(ncase--)
{
scanf("%d%d",&n,&q);
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
num[i]=n-i+1;
update(i,1);
}
cur=n;
for(i=1;i<=q;i++)
{
scanf("%d",&x);
printf("%d",n-query(num[x]));
if(i!=q)
printf(" ");
update(num[x],-1);
num[x]=++cur;
update(num[x],1);
}
printf("\n");
}
return 0;
}