假设每秒进行一次操作,用一个数组保存每个电影上一次操作的时间da[i]=t。
那么要知道第i部电影上面有多少只要找到“时间>da[i]”的有多少个就行了,这一步可以用树状数组实现。
x[t]表示某个时间t是否在da数组中,用树状数组统计sum{x[i] ,i>da[k]}
我们可以把电影的初始状态看成以n,n-1,n-2.....1的顺序全部操作了一遍。
注意每次查询后要把之前的旧时间清除,且更新da数组.
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include<cstdio> #include<cstring> #include<cstdlib> #include<algorithm> #include<iostream> #include<sstream> #include<cmath> #include<climits> #include<string> #include<map> #include<queue> #include<vector> #include<stack> #include<set> using namespace std; typedef long long ll; typedef pair<int,int> pii; #define pb(a) push_back(a) #define INF 0x1f1f1f1f #define lson idx<<1,l,mid #define rson idx<<1|1,mid+1,r #define PI 3.1415926535898 template<class T> T min(const T& a,const T& b,const T& c) { return min(min(a,b),min(a,c)); } template<class T> T max(const T& a,const T& b,const T& c) { return max(max(a,b),max(a,c)); } void debug() { #ifdef ONLINE_JUDGE #else freopen("d:\in.txt","r",stdin); freopen("d:\out1.txt","w",stdout); #endif } int getch() { int ch; while((ch=getchar())!=EOF) { if(ch!=' '&&ch!=' ')return ch; } return EOF; } int da[200200]; int c[200200]; int n,m; int add(int x,int v) { while(x<=200000) { c[x]+=v; x=x+(x&-x); } return 0; } int sum(int x) { int a=0; while(x>0) { a+=c[x]; x=x-(x&-x); } return a; } int main() { int t; scanf("%d",&t); for(int ca=1;ca<=t;ca++) { scanf("%d%d",&n,&m); memset(c,0,sizeof(c)); for(int i=1;i<=n;i++) { add(i,1); da[i]=n-i+1; } for(int i=1;i<=m;i++) { int v; scanf("%d",&v); printf("%d%c",sum(200000)-sum(da[v]),i==m?' ':' '); add(da[v],-1); add(i+n,1); da[v]=i+n; } } return 0; }