luogu 3960 列队
noip2017 D2T3 列队 某zz选手当时直接放弃了写了50还写错了
题目大意:
有一个n行m列的方阵,第i行j列的点编号为(i-1)m+j
每次把第x行y列的点拿出来,然后把这一行它之后的点都向左推,把最后一列x行之后的点都向上推
然后把拿出来的点放到最后一个位置,询问这个点的编号
思路:
因为n+q并不大 可以动态开点每行维护一个权值线段树 并对最后一行单独维护
对于新进来的点使用vector维护
1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstdlib> 5 #include<cstring> 6 #include<algorithm> 7 #include<vector> 8 #include<queue> 9 #define inf 2139062143 10 #define ll long long 11 #define MAXN 300100 12 using namespace std; 13 inline int read() 14 { 15 int x=0,f=1;char ch=getchar(); 16 while(!isdigit(ch)) {if(ch=='-') f=-1;ch=getchar();} 17 while(isdigit(ch)) {x=x*10+ch-'0';ch=getchar();} 18 return x*f; 19 } 20 int n,m,q,rt[MAXN],ls[MAXN*20],rs[MAXN*20],sum[MAXN*20],sz; 21 ll ans[MAXN<<1]; 22 vector <ll> vec[MAXN]; 23 int query(int &k,int l,int r,int x) 24 { 25 if(!k) k=++sz,sum[k]=r-l+1; 26 sum[k]--; 27 if(l==r) return l; 28 int mid=l+r>>1,sl=ls[k]?sum[ls[k]]:mid-l+1; 29 if(x<=sl) query(ls[k],l,mid,x); 30 else query(rs[k],mid+1,r,x-sl); 31 } 32 int main() 33 { 34 n=read(),m=read(),q=read();int a,b,res; 35 for(int i=1;i<=n;i++) ans[i]=1ll*i*m; 36 for(int i=n+1;i<=n+q;i++) 37 { 38 a=read(),b=read(); 39 if(b==m) ans[i]=ans[query(rt[0],1,n+q,a)]; 40 else 41 { 42 res=query(rt[a],1,m+q,b); 43 if(res<m) ans[i]=(a-1ll)*m*1ll+res; 44 else ans[i]=vec[a][res-m]; 45 vec[a].push_back(ans[query(rt[0],1,n+q,a)]); 46 } 47 printf("%lld\n",ans[i]); 48 } 49 }