NOIP2017 Day2T3
每次操作(x,y)只对第x行和最后一列有影响.
所以维护n+1棵线段树.
第1~n棵维护1~n行每行的状态.
第n+1棵维护最后一列的状态.
但是空间好像会炸.
没关系,我们来动态开点.
动态开点的空间复杂度为O(q*log(max(n,m)+q)),非常优秀.
正紧点,时间复杂度也为O(q*log(max(n,m)+q)).
54行优秀代码
#include<stdio.h> #include<vector> typedef long long ll; const int N=1000005; std::vector<ll>v[N>>1]; int root[N]; struct Tree{int ls,rs,sum;}tr[N<<2]; int tot,n,m,q,len,x,y; inline void change(int &k,int l,int r,int p){ if(!k)k=++tot; ++tr[k].sum; if(l==r)return; int mid=(l+r)>>1; p<=mid?change(tr[k].ls,l,mid,p):change(tr[k].rs,mid+1,r,p); } inline int query(int &k,int l,int r,int p){ if(!k)k=++tot; if(l==r)return l; int mid=(l+r)>>1; int data=mid-l+1-tr[tr[k].ls].sum; return p<=data?query(tr[k].ls,l,mid,p):query(tr[k].rs,mid+1,r,p-data); } inline ll query_r(int x,ll y){ int pos=query(root[n+1],1,len,x); change(root[n+1],1,len,pos); ll ans=pos<=n?1ll*pos*m:v[n+1][pos-n-1]; v[n+1].push_back(y?y:ans); return ans; } inline ll query_l(int x,int y){ int pos=query(root[x],1,len,y); change(root[x],1,len,pos); ll ans=pos<m?(1ll*(x-1)*m+1ll*pos):v[x][pos-m]; v[x].push_back(query_r(x,ans)); return ans; } inline int read(){ char c; while(c=getchar(),c==' '||c=='\n'); int data=c-48; while(c=getchar(),c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48; return data; } inline int max(int a,int b){ return a>b?a:b; } int main(){ n=read();m=read();q=read();len=max(n,m)+q; while(q--){ x=read();y=read(); printf("%lld\n",y==m?query_r(x,0):query_l(x,y)); } return 0; }