题目大意:有一个人有n个光盘,从下到上依次是n-1,现在给出操作m,意思是要把光盘m拿出来并放到最上面,并问操作前,关盘m上面有多少个光盘
解题思路:用两个数组,pos数组纪录每个数所在的位置,t数组纪录这个数前面有多少个光盘
将第n个放在第一个,第n-1个放在第2个,依此类推,然后更新t数组,这样的话,如果要求编号为m的光盘上面有多少个光盘,就可以直接用sum(maxn-1) - sum(pos[m])
然后,每次更新的时候,先更新pos[m]后面的,依此-1,然后再将pos[m]设置为当前这些光盘的最后面,再更新pos[m]后面的
#include<cstdio>
#include<cstring>
const int maxn = 100010 << 2;
int t[maxn], pos[maxn], n, m;
int lowbit(int x) {
return x&(-x);
}
void Update(int x, int d) {
while(x < maxn) {
t[x] += d;
x += lowbit(x);
}
}
int sum(int x) {
int ans = 0;
while(x > 0) {
ans += t[x];
x -= lowbit(x);
}
return ans;
}
void init() {
for(int i = 1; i <= n; i++) {
Update(i,1);
pos[i] = n - i + 1;
}
}
int main() {
int test;
scanf("%d", &test);
while(test--) {
scanf("%d%d", &n, &m);
memset(t,0,sizeof(t));
init();
int cur = n, x;
for(int i = 0; i < m; i++) {
scanf("%d", &x);
int ans = sum(maxn-1) - sum(pos[x]);
printf("%d%c", ans, i == m - 1 ? '\n':' ');
Update(pos[x],-1);
pos[x] = ++cur;
Update(pos[x],1);
}
}
return 0;
}