树状数组的简单用法:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5 + 5;
int N, M, fnew[maxn*2]; //进行操作的树状数组
int pos[maxn]; //保存原位置的数组
inline int lowbit(int x) //能够求出来管辖的区域范围
{
return x&(-x);
}
//树状数组添加或者删除修改元素
void add(int p, int num)
{
while(p <= 2*maxn)
{
fnew[p] += num;
p += lowbit(p);
}
}
//树状数组求和
int Sum(int x)
{
int sum = 0;
while(x > 0)
{
sum += fnew[x];
x -= lowbit(x); //转移到它的前一个子树
}
return sum;
}
int main()
{
int x;
while(cin >> x)
{
cout << lowbit(x) << endl;
x -= lowbit(x);
cout << x << endl;
}
return 0;
}
题目代码:
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn = 100010;
int N, M;
int pos[maxn], fnew[maxn*2];
inline int lowbit(int x)
{
return x &(-x);
}
void add(int p, int v)
{
while(p <= 2*maxn)
{
fnew[p] += v;
p += lowbit(p);
}
}
int Sum(int x)
{
int sum = 0;
while(x > 0)
{
sum += fnew[x];
x -= lowbit(x);
}
return sum;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &N, &M);
memset(fnew, 0, sizeof(fnew));
for(int i = 1, j = N; i <= N; i++, j--) //初始化
{
pos[i] = j;
add(pos[i], 1);
}
int n = N, x;
for(int i = 1; i <= M; i++)
{
scanf("%d", &x);
printf("%d", n-Sum(pos[x]));
if(i == M) printf("\n");
else printf(" ");
add(pos[x], -1);
pos[x] = ++N;
add(pos[x], 1);
}
}
return 0;
}