题目链接
测试点1~10
观察到$q\le 500$,那我们duck只用暴力维护$500$行和最后一列。
换种说法,对行离散化,每次暴力取出数并且平移数组,时间复杂度和空间复杂度都是$O(nq)$。
测试点11~16
所有$x=1$,那就是只会用到第一行和最后一列。
思考一下,我们每次找到第$k$个数,放到最后面。
我们提取一个数出来,发现它后面的所有数的编号都会减一。
也许我们可以考虑用数据结构维护这些编号?然后每次询问就来一个二分查找,辅助数组存数值。看起来很可做。
一个想法,初始每个位置上存对应的编号,每次找到第$k$个数,对它后面进行区间减一,然后序列长度增加,把它放到最后,单点赋个值。这个线段树很好做。
还有一个思路,初始每个位置上存一,每次找到这个数,单点减一,然后序列长度增加,最后这个位置加一,每次查询前缀和。这个树状数组很好做。
所以我们选择树状数组。
代码1(80分)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<iostream> #include<cstdio> #include<cstring> #include<cmath> #include<algorithm> #include<vector> #include<queue> #include<map> #include<set> #define IL inline #define RG register #define _1 first #define _2 second using namespace std; typedef long long LL; #define RI RG int #define RL RG LL const int N=3e5; const int N1=5e4; const int Q1=500; IL void qr(RI &x){ x=0; RG char ch=getchar(); while(!isdigit(ch)) ch=getchar(); for(;isdigit(ch);ch=getchar()) x=(x<<3)+(x<<1)+ch-'0'; } IL void qw(RL x,RG char ch){ RI k=0,s[13]; if(!x) s[k=1]=0; else for(;x;x/=10) s[++k]=x%10; for(;k;k--) putchar(s[k]+'0'); putchar(ch); } int n,m,q; struct Pr{ int x,y,d; }a[N+3]; int t1[Q1+3]; IL int bin1(RI l,RI r,RI x){ RI mid,ans; while(l<=r){ mid=(l+r)>>1; if(x<=t1[mid]){ r=mid-1; ans=mid; } else l=mid+1; } return ans; } LL p1[Q1+3][N1+3]; IL void sol1(){ for(RI i=1;i<=q;i++) t1[i]=a[i].x; sort(t1+1,t1+q+1); RI mm=1; for(RI i=2;i<=q;i++) if(t1[i]!=t1[i-1]) t1[++mm]=t1[i]; for(RI i=1;i<=q;i++) a[i].x=bin1(1,mm,a[i].x); for(RI i=1;i<=mm;i++) for(RI j=1;j<m;j++) p1[i][j]=(LL)(t1[i]-1)*m+j; for(RI i=1;i<=n;i++) p1[0][i]=(LL)i*m; for(RI k=1;k<=q;k++){ RL tmp; if(a[k].y==m) tmp=p1[0][t1[a[k].x]]; else tmp=p1[a[k].x][a[k].y]; qw(tmp,'\n'); for(RI i=a[k].y;i<m-1;i++) p1[a[k].x][i]=p1[a[k].x][i+1]; p1[a[k].x][m-1]=p1[0][t1[a[k].x]]; for(RI i=t1[a[k].x];i<n;i++) p1[0][i]=p1[0][i+1]; p1[0][n]=tmp; } } IL bool check2(){ for(RI i=1;i<=q;i++) if(a[i].x!=1) return false; return true; } int k,s2[N*3+3]; LL t2[N*3+2]; IL int lowbit(RI x){return x&(-x);} IL void mdf(RI p,RI x){ for(;p<=n+m+q;p+=lowbit(p)) s2[p]+=x; } IL int qry(RI p){ RI ret=0; for(;p;p-=lowbit(p)) ret+=s2[p]; return ret; } IL int bin2(RI l,RI r,RI x){ RI mid,ans; while(l<=r){ mid=(l+r)>>1; if(x<=qry(mid)){ r=mid-1; ans=mid; } else l=mid+1; } return ans; } IL void sol2(){ for(RI i=1;i<=n+m-1;i++) mdf(i,1); for(RI i=1;i<=m;i++) t2[i]=i; for(RI i=m+1,j=2;i<=n+m-1;i++,j++) t2[i]=(LL)j*m; k=n+m-1; for(RI i=1;i<=q;i++){ RI pos=bin2(1,k,a[i].y); qw(t2[pos],'\n'); mdf(pos,-1); mdf(++k,1); t2[k]=t2[pos]; } } IL void sol3(){ } int main(){ qr(n); qr(m); qr(q); for(int i=1;i<=q;i++){ qr(a[i].x); qr(a[i].y); a[i].d=i; } if(q<=500) sol1(); else if(check2()) sol2(); else sol3(); return 0; }