[关闭]
@ysner 2018-10-25T21:10:41.000000Z 字数 1617 阅读 1892

[noip2017]列队

线段树 主席树 vector


题面

无人不知,无人不晓

解析

想想如何简化题目中的操作。
一个人到,暴力模拟的复杂度是
考虑节省掉移动整行整列的复杂度。

实际上,不如让一个人移走后留下的位置空着。
这样一行最多只有,是可以维护的。

于是用棵线段树维护一下每一行中,区间内有多少个空位置。
这样就可以查出一行的第个在哪里。

当然,如果每行线段树都开全,空间复杂度开不下。
所以需要动态开点。

注意到只有行和第列有可能新加入数。
可以用存一下,每行新加入了什么数(第列不包含在内)。
还有一个存第列新加入的数。

另外,删掉中的数也是级别的。所以每行的线段树也要维护中的空位置。

这么以来,操作就转化为在数据结构的基础上模拟了。

  1. #include<iostream>
  2. #include<cmath>
  3. #include<cstdio>
  4. #include<cstdlib>
  5. #include<cstring>
  6. #include<algorithm>
  7. #include<vector>
  8. #define ll long long
  9. #define re register
  10. #define il inline
  11. #define pb push_back
  12. #define fp(i,a,b) for(re int i=a;i<=b;++i)
  13. #define fq(i,a,b) for(re int i=a;i>=b;--i)
  14. using namespace std;
  15. const int N=3e5+100;
  16. int n,m,q,t[N*100],tot,rt[N*100],tim,ls[N*100],rs[N*100];
  17. vector<ll>V[N];
  18. il ll gi()
  19. {
  20. re ll x=0,t=1;
  21. re char ch=getchar();
  22. while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
  23. if(ch=='-') t=-1,ch=getchar();
  24. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  25. return x*t;
  26. }
  27. il void Inherit(re int &x)
  28. {
  29. rt[++tim]=rt[x];t[tim]=t[x];ls[tim]=ls[x];rs[tim]=rs[x];x=tim;
  30. }
  31. il int Query(re int &x,re int l,re int r,re int k)
  32. {
  33. Inherit(x);
  34. if(l==r) {t[x]=1;return l;}
  35. re int mid=l+r>>1,sz=mid-l+1-t[ls[x]],ans;
  36. if(k<=sz) ans=Query(ls[x],l,mid,k);
  37. else ans=Query(rs[x],mid+1,r,k-sz);
  38. t[x]=t[ls[x]]+t[rs[x]];
  39. return ans;
  40. }
  41. il ll find(re int i,re int k)
  42. {
  43. re ll ans=Query(rt[i],1,tot,k),l=(i<=n?m-1:n);
  44. if(ans<=l) return i<=n?1ll*(i-1)*m+ans:ans*m;
  45. else return V[i][ans-l-1];
  46. }
  47. int main()
  48. {
  49. n=gi();m=gi();q=gi();tot=max(n,m)+q;
  50. fp(i,1,n+1) rt[i]=++tim;
  51. fp(i,1,q)
  52. {
  53. re int x=gi(),y=gi();re ll p1,p2;
  54. if(y^m)
  55. {
  56. p1=find(x,y);V[n+1].pb(p1);//a new member on lie m
  57. p2=find(n+1,x);V[x].pb(p2);//new one ->the n_th line
  58. }
  59. else p1=find(n+1,x),V[n+1].pb(p1);
  60. printf("%lld\n",p1);
  61. }
  62. return 0;
  63. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注