[关闭]
@ysner 2018-04-24T22:13:16.000000Z 字数 2854 阅读 1864

LuoguP4246 [SHOI2008]堵塞的交通

线段树


题面

给一个网格,每次把相邻两点连通性改为,询问两点是否联通。

解析

线段树神题。。。
码量巨大,细节巨多。。。

从一座城市走到另一座城市,一共有4种方案。

若两城市在同一行(比如说,),那么:

s1-->s2
s1-->s3,s3-->s2
s1-->s4,s4-->s2
s1-->s3,s3-->s4,s4-->s2


若两城市不在同一行(比如说,),那么:

s1-->s3,s3-->s4
s1-->s2,s2-->s4
s1-->s3,s3-->s2,s2-->s4
s1-->s4


  而我们怎么维护这个东西呢?考虑用线段树。每个节点表示区间[l,r]的矩形,并且记录8个变量:。其中,

  1. // luogu-judger-enable-o2
  2. // luogu-judger-enable-o2
  3. #include<iostream>
  4. #include<cmath>
  5. #include<cstring>
  6. #include<cstdio>
  7. #include<cstdlib>
  8. #include<algorithm>
  9. #define ll long long
  10. #define re register
  11. #define il inline
  12. #define ls x<<1
  13. #define rs x<<1|1
  14. #define fp(i,a,b) for(re int i=a;i<=b;i++)
  15. #define fq(i,a,b) for(re int i=a;i>=b;i--)
  16. using namespace std;
  17. const int N=1e6+100;
  18. struct way{int l,r;}a[N<<2];
  19. struct seg{int U,D,l,r,u,d,p,q;}t[N<<2];
  20. int c,r1,r2,c1,c2;
  21. char s[10];
  22. il int gi()
  23. {
  24. re int x=0,t=1;
  25. re char ch=getchar();
  26. while((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
  27. if(ch=='-') t=-1,ch=getchar();
  28. while(ch>='0'&&ch<='9') x=x*10+ch-48,ch=getchar();
  29. return x*t;
  30. }
  31. il void Merge(seg &x,seg l,seg r)
  32. {
  33. x.l=l.l|(l.u&x.U&r.l&x.D&l.d);
  34. x.r=r.r|(r.u&x.U&l.r&x.D&r.d);
  35. x.u=(l.u&x.U&r.u)|(l.q&x.D&r.p);
  36. x.d=(l.d&x.D&r.d)|(l.p&x.U&r.q);
  37. x.q=(l.u&x.U&r.q)|(l.q&x.D&r.d);
  38. x.p=(l.d&x.D&r.p)|(l.p&x.U&r.u);
  39. }
  40. il void Build(re int x,re int l,re int r)
  41. {
  42. a[x]=(way){l,r};re int mid=l+r>>1;
  43. if(l==r) {t[x].U=t[x].D=t[x].u=t[x].d=1;return;}
  44. Build(ls,l,mid);Build(rs,mid+1,r);
  45. }
  46. il void Updater(re int x,re int p,re int y,re int w)
  47. {
  48. re int l=a[x].l,r=a[x].r;re int mid=l+r>>1;
  49. if(p==mid)
  50. {
  51. if(y==1) t[x].U=w;else t[x].D=w;
  52. Merge(t[x],t[ls],t[rs]);
  53. return;
  54. }
  55. if(p<=mid) Updater(ls,p,y,w);else Updater(rs,p,y,w);
  56. Merge(t[x],t[ls],t[rs]);
  57. }
  58. il void Updatec(re int x,re int p,re int w)
  59. {
  60. re int l=a[x].l,r=a[x].r;re int mid=l+r>>1;
  61. if(l==r) {t[x].l=t[x].r=t[x].p=t[x].q=w;return;}
  62. if(p<=mid) Updatec(ls,p,w);else Updatec(rs,p,w);
  63. Merge(t[x],t[ls],t[rs]);
  64. }
  65. seg Query(re int x,re int ql,re int qr)
  66. {
  67. re int l=a[x].l,r=a[x].r;re int mid=l+r>>1;
  68. if(ql<=l&&r<=qr) return t[x];
  69. if(qr<=mid) return Query(ls,ql,qr);
  70. else if(ql>mid) return Query(rs,ql,qr);
  71. else
  72. {
  73. seg res=t[x];
  74. Merge(res,Query(ls,ql,qr),Query(rs,ql,qr));
  75. return res;
  76. }
  77. }
  78. int main()
  79. {
  80. c=gi();
  81. Build(1,1,c);
  82. while(233)
  83. {
  84. scanf("%s",s);
  85. if(s[0]=='E') break;
  86. r1=gi();c1=gi();r2=gi();c2=gi();
  87. if(c1>c2) swap(c1,c2),swap(r1,r2);
  88. if(s[0]=='O')
  89. if(r1==r2) Updater(1,c1,r1,1);else Updatec(1,c1,1);
  90. if(s[0]=='C')
  91. if(r1==r2) Updater(1,c1,r1,0);else Updatec(1,c1,0);
  92. if(s[0]=='A')
  93. {
  94. seg l=Query(1,1,c1),x=Query(1,c1,c2),r=Query(1,c2,c);
  95. re int ans=0;
  96. if(r1==1&&r2==1)
  97. ans=x.u|(l.r&x.p)|(x.q&r.l)|(l.r&x.d&r.l);
  98. if(r1==1&&r2==2)
  99. ans=x.q|(l.r&x.d)|(x.u&r.l)|(l.r&x.p&r.l);
  100. if(r1==2&&r2==1)
  101. ans=x.p|(l.r&x.u)|(x.d&r.l)|(l.r&x.q&r.l);
  102. if(r1==2&&r2==2)
  103. ans=x.d|(l.r&x.q)|(x.p&r.l)|(l.r&x.u&r.l);
  104. puts(ans?"Y":"N");
  105. }
  106. }
  107. return 0;
  108. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注