BZOJ4422 : [Cerc2015]Cow Confinement

r囧r小猫 2022-03-30 10:16 230阅读 0赞

从右往左扫描线,用线段树维护扫描线上每一个点能达到的花的数量,并支持最近篱笆的查询。

对于一朵花,找到它上方最近的篱笆,那么它对这中间的每头牛的贡献都是$1$。

当扫到一个篱笆的右边界时,这中间的答案都要清零。

当扫到一个篱笆的左边界时,这中间的答案同理都要清零,但是要向上直到最近的篱笆为止都加上下面的答案。

这中间对这个篱笆右下角的贡献会重复计数,因此需要减掉。

时间复杂度$O(n\log n)$。

  1. #include<cstdio>
  2. #include<algorithm>
  3. const int N=1000005,M=2100000,U=200010;
  4. int n,m,cnt,i,v[M],ta[M],tc[M],f[U],ans[U];
  5. struct E{
  6. int x,l,r,t,i;
  7. E(){}
  8. E(int _x,int _l,int _r,int _t,int _i){x=_x,l=_l,r=_r,t=_t,i=_i;}
  9. }e[U*5];
  10. inline bool cmp(const E&a,const E&b){
  11. if(a.x!=b.x)return a.x>b.x;
  12. if(a.t!=b.t)return a.t<b.t;
  13. return a.l<b.l;
  14. }
  15. inline void read(int&a){char c;while(!(((c=getchar())>='0')&&(c<='9')));a=c-'0';while(((c=getchar())>='0')&&(c<='9'))(a*=10)+=c-'0';}
  16. inline void taga1(int x,int p){if(~tc[x])tc[x]+=p;else ta[x]+=p;}
  17. inline void tagc1(int x,int p){ta[x]=0;tc[x]=p;}
  18. inline void pb(int x){
  19. if(ta[x])taga1(x<<1,ta[x]),taga1(x<<1|1,ta[x]),ta[x]=0;
  20. if(~tc[x])tagc1(x<<1,tc[x]),tagc1(x<<1|1,tc[x]),tc[x]=-1;
  21. }
  22. void change(int x,int a,int b,int c,int p){
  23. if(a==b){v[x]=p?a:0;return;}
  24. int mid=(a+b)>>1;
  25. c<=mid?change(x<<1,a,mid,c,p):change(x<<1|1,mid+1,b,c,p);
  26. v[x]=v[x<<1|1]?v[x<<1|1]:v[x<<1];
  27. }
  28. int get(int x,int a,int b,int d){
  29. if(b<=d)return v[x];
  30. int mid=(a+b)>>1,t=0;
  31. if(d>mid)t=get(x<<1|1,mid+1,b,d);
  32. if(t)return t;
  33. return get(x<<1,a,mid,d);
  34. }
  35. void add(int x,int a,int b,int c,int d,int p){
  36. if(c<=a&&b<=d){taga1(x,p);return;}
  37. pb(x);
  38. int mid=(a+b)>>1;
  39. if(c<=mid)add(x<<1,a,mid,c,d,p);
  40. if(d>mid)add(x<<1|1,mid+1,b,c,d,p);
  41. }
  42. void clear(int x,int a,int b,int c,int d){
  43. if(c<=a&&b<=d){tagc1(x,0);return;}
  44. pb(x);
  45. int mid=(a+b)>>1;
  46. if(c<=mid)clear(x<<1,a,mid,c,d);
  47. if(d>mid)clear(x<<1|1,mid+1,b,c,d);
  48. }
  49. int ask(int x,int a,int b,int c){
  50. if(a==b)return ta[x]+tc[x];
  51. pb(x);
  52. int mid=(a+b)>>1;
  53. return c<=mid?ask(x<<1,a,mid,c):ask(x<<1|1,mid+1,b,c);
  54. }
  55. int main(){
  56. read(m);
  57. for(i=1;i<=m;i++){
  58. int xl,xr,yl,yr;
  59. read(xl),read(yl),read(xr),read(yr);
  60. e[++cnt]=E(yr,xl,xr,-2,0);
  61. e[++cnt]=E(yl-1,xl,xr,-1,i);
  62. e[++cnt]=E(yr+1,xr+1,0,1,-i);
  63. }
  64. read(m);
  65. while(m--){
  66. int x,y;
  67. read(x),read(y);
  68. e[++cnt]=E(y,x,0,0,0);
  69. }
  70. read(n);
  71. for(i=1;i<=n;i++){
  72. int x,y;
  73. read(x),read(y);
  74. e[++cnt]=E(y,x,0,1,i);
  75. }
  76. std::sort(e+1,e+cnt+1,cmp);
  77. for(i=1;i<=cnt;i++){
  78. int l=e[i].l,r=e[i].r;
  79. if(e[i].t==-1){
  80. change(1,0,N,l-1,0);
  81. change(1,0,N,r,0);
  82. int o=get(1,0,N,l-1);
  83. clear(1,0,N,l,r);
  84. add(1,0,N,o+1,r,ask(1,0,N,r+1));
  85. if(o+1<=l-1&&f[e[i].i])add(1,0,N,o+1,l-1,-f[e[i].i]);
  86. }else if(e[i].t==-2){
  87. change(1,0,N,l-1,1);
  88. change(1,0,N,r,1);
  89. clear(1,0,N,l,r);
  90. }else if(!e[i].t)add(1,0,N,get(1,0,N,l-1)+1,l,1);
  91. else{
  92. if(e[i].i>0)ans[e[i].i]=ask(1,0,N,l);
  93. else f[-e[i].i]=ask(1,0,N,l);
  94. }
  95. }
  96. for(i=1;i<=n;i++)printf("%d\n",ans[i]);
  97. return 0;
  98. }

发表评论

表情:
评论列表 (有 0 条评论,230人围观)

还没有评论,来说两句吧...

相关阅读

    相关 [CERC2017]Gambling Guide

    [题目][Link 1] 看起来非常随机游走,但是由于我们可以停在原地,所以变得不是非常一样 设\\(f\_x\\)表示从\\(x\\)到\\(n\\)的期望距离 如果我

    相关 BZOJ4422 : [Cerc2015]Cow Confinement

    从右往左扫描线,用线段树维护扫描线上每一个点能达到的花的数量,并支持最近篱笆的查询。 对于一朵花,找到它上方最近的篱笆,那么它对这中间的每头牛的贡献都是$1$。 当扫到一个

    相关 BZOJ4326: NOIP2015 运输计划

    题目大意:给出一棵带边权的树和m条路径,可以将一条边的边权变成0,求问最长的路径最短是多少。 题解: 暴力算法:将每条边变不变,用数据结构维护,更新答案。 这样显然过不掉