https://www.luogu.org/problemnew/show/P3960
树状数组预处理之后直接搞就可以了,也不是很好解释,反正就是一个模拟过程的暴力用树状数组维护,还挺巧妙的。
我为什么考场上想不出来嘤嘤嘤
1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<vector> 7 using namespace std; 8 const int maxn=600010; 9 int n,m,q; 10 int xx[maxn]={},yy[maxn]={}; 11 int num[maxn]={},z[maxn]={}; 12 int lag[maxn]={}; 13 int t[maxn]={},mx; 14 vector<int>id[maxn]; 15 vector<int>val[maxn]; 16 vector<long long >shu[maxn]; 17 void add(int x,int v){ 18 while(x<=mx){ 19 t[x]+=v; 20 x+=(x&-x); 21 } 22 } 23 int getit(int x){ 24 int tsn=0; 25 while(x){ 26 tsn+=t[x]; 27 x-=(x&-x); 28 }return tsn; 29 } 30 int Find(int x){ 31 int l=0,r=mx,mid; 32 while(l<r){ 33 mid=(l+r)/2; 34 if(getit(mid)<x)l=mid+1; 35 else r=mid; 36 } 37 return l; 38 } 39 int main(){ 40 scanf("%d%d%d",&n,&m,&q); 41 mx=max(n,m)+q; 42 for(int i=1;i<=q;i++){ 43 scanf("%d%d",&xx[i],&yy[i]); 44 if(yy[i]!=m){ 45 val[xx[i]].push_back(yy[i]); 46 id[xx[i]].push_back(i); 47 } 48 else 49 z[i]=1; 50 } 51 for(int i=1;i<=mx;i++)add(i,1); 52 for(int i=1;i<=n;i++){ 53 int siz=id[i].size(); 54 for(int j=0;j<siz;j++){ 55 num[id[i][j]]=Find(val[i][j]); 56 add(num[id[i][j]],-1); 57 } 58 for(int j=0;j<siz;j++)add(num[id[i][j]],1); 59 } 60 long long ans; 61 for(int i=0;i<=n;i++)shu[0].push_back((long long)i*m); 62 lag[0]=m; 63 for(int i=1;i<=q;i++){ 64 if(z[i]){ 65 ans=shu[0][Find(xx[i])]; 66 add(Find(xx[i]),-1); 67 } 68 else if(num[i]<=m+lag[xx[i]]-1){ 69 ans=num[i]<m?(long long)(xx[i]-1)*m+num[i]:shu[xx[i]][num[i]-m]; 70 shu[xx[i]].push_back(shu[0][Find(xx[i])]); 71 lag[xx[i]]++; 72 add(Find(xx[i]),-1); 73 } 74 else{ 75 ans=shu[0][Find(num[i]-m-lag[xx[i]]+xx[i])]; 76 add(Find(num[i]-m-lag[xx[i]]+xx[i]),-1); 77 } 78 shu[0].push_back(ans);lag[0]++; 79 printf("%lld ",ans); 80 } 81 return 0; 82 }