• BZOJ 1018 线段树维护连通性


    这个题我总是想用循环完成转移,最后发现,还是手工枚举最靠谱~

    建立线段树,线段树的每个节点(代表的是区间)维护以上六个值,true表示连通,false表示不连通,具体可以看我的代码~

    View Code
      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstring>
      4 #include <cstdlib>
      5 #include <algorithm>
      6 
      7 #define N 111111
      8 
      9 using namespace std;
     10 
     11 struct DAT
     12 {
     13     bool v[2],s[2],x[2];
     14     void prt() {printf("s:%d      %d\nx:%d      %d\nv:%d      %d\n\n",s[0],s[1],x[0],x[1],v[0],v[1]);}
     15 }dat[N<<2];
     16 
     17 bool a[N][2][2];
     18 int n,r1,r2,c1,c2;
     19 int dx[3]={-1,0,1};
     20 int dy[3]={0,1,0};
     21 
     22 inline void build(int u,int l,int r)
     23 {
     24     if(l==r) {dat[u].s[0]=dat[u].s[1]=true;return;}
     25     int mid=(l+r)>>1;
     26     build(u<<1,l,mid); build(u<<1|1,mid+1,r);
     27 }
     28 
     29 inline void pack(DAT &u,DAT &ls,DAT &rs,int mid)
     30 {
     31     u.x[0]=ls.x[0]||(ls.s[0]&&a[mid][0][0]&&rs.x[0]&&a[mid][1][0]&&ls.s[1]);//左上-右上 
     32     u.x[1]=rs.x[1]||(rs.s[0]&&a[mid][0][0]&&ls.x[1]&&a[mid][1][0]&&rs.s[1]);//左下-右下 
     33     u.s[0]=(ls.s[0]&&a[mid][0][0]&&rs.s[0])||(ls.v[0]&&a[mid][1][0]&&rs.v[1]);//左上-左下
     34     u.s[1]=(ls.s[1]&&a[mid][1][0]&&rs.s[1])||(ls.v[1]&&a[mid][0][0]&&rs.v[0]);//右上-右下
     35     u.v[0]=(ls.s[0]&&a[mid][0][0]&&rs.v[0])||(ls.v[0]&&a[mid][1][0]&&rs.s[1]);//左上-右下
     36     u.v[1]=(ls.s[1]&&a[mid][1][0]&&rs.v[1])||(ls.v[1]&&a[mid][0][0]&&rs.s[0]);//右上-左下 
     37 }
     38 
     39 inline void updata(int u,int l,int r,int p)
     40 {
     41     if(l==r)
     42     {
     43         dat[u].x[0]=dat[u].x[1]=dat[u].v[1]=dat[u].v[0]=a[p][0][1];
     44         dat[u].s[0]=dat[u].s[1]=true;
     45         return;
     46     }
     47     int mid=(l+r)>>1;
     48     if(p<=mid) updata(u<<1,l,mid,p);
     49     else updata(u<<1|1,mid+1,r,p);
     50     pack(dat[u],dat[u<<1],dat[u<<1|1],mid);
     51 }
     52 
     53 inline void change(bool pd)
     54 {
     55     if(r1>r2) swap(r1,r2),swap(c1,c2);
     56     int dir;
     57     for(int i=0;i<3;i++)
     58         if(c1+dx[i]==c2&&r1+dy[i]==r2) dir=i;
     59     if(dir==0) a[c2][r2][0]=pd,updata(1,1,n,c2);
     60     else if(dir==1) a[c1][0][1]=pd,updata(1,1,n,c1);
     61     else a[c1][r1][0]=pd,updata(1,1,n,c1);
     62 }
     63 
     64 inline void getpack(DAT &p,int u,int L,int R,int l,int r)
     65 {
     66     if(l<=L&&r>=R) {p=dat[u];return;}
     67     int MID=(L+R)>>1;
     68     if(r<=MID) getpack(p,u<<1,L,MID,l,r);
     69     else if(l>=MID+1) getpack(p,u<<1|1,MID+1,R,l,r);
     70     else
     71     {
     72         DAT tmp1,tmp2;
     73         getpack(tmp1,u<<1,L,MID,l,MID);
     74         getpack(tmp2,u<<1|1,MID+1,R,MID+1,r);
     75         pack(p,tmp1,tmp2,MID);
     76     }
     77 }
     78 
     79 inline void getans()
     80 {
     81     if(c1>c2) swap(c1,c2),swap(r1,r2);
     82     DAT pa,pb,pc;
     83     getpack(pa,1,1,n,1,c1);
     84     getpack(pb,1,1,n,c1,c2);
     85     getpack(pc,1,1,n,c2,n);
     86     if(r1==r2)
     87     {
     88         if(r1==0)
     89         {
     90             if(pb.s[0]||(pa.x[1]&&pb.v[1])||(pc.x[0]&&pb.v[0])||(pa.x[1]&&pb.s[1]&&pc.x[0])) puts("Y");
     91             else puts("N");
     92         }
     93         else
     94         {
     95             if(pb.s[1]||(pa.x[1]&&pb.v[0])||(pc.x[0]&&pb.v[1])||(pa.x[1]&&pb.s[0]&&pc.x[0])) puts("Y");
     96             else puts("N");
     97         }
     98     }
     99     else
    100     {
    101         if(r1==0)
    102         {
    103             if(pb.v[0]||(pa.x[1]&&pb.s[1])||(pc.x[0]&&pb.s[0])) puts("Y");
    104             else puts("N");
    105         }
    106         else
    107         {
    108             if(pb.v[1]||(pa.x[1]&&pb.s[0])||(pc.x[0]&&pb.s[1])) puts("Y");
    109             else puts("N");
    110         }
    111     }
    112 }
    113 
    114 inline void go()
    115 {
    116     char str[10];
    117     scanf("%d",&n);
    118     build(1,1,n);
    119     while(scanf("%s",str))
    120     {
    121         if(str[0]=='E') break;
    122         scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
    123         r1--; r2--;
    124         if(str[0]=='O') change(1);
    125         else if(str[0]=='C') change(0);
    126         else getans();
    127     }
    128 }
    129 
    130 int main()
    131 {
    132     go();
    133     return 0;
    134 }

    感觉这个题还是挺神的~

    没有人能阻止我前进的步伐,除了我自己!
  • 相关阅读:
    (五)串口通讯方式设置
    (四)计算机上电自启动
    (三)磁盘分区
    (一)老毛桃U盘启动盘制作
    (二)操作系统安装
    计算机常见问题1:计算机网口问题
    Java日志打印方法
    MySQL数据库常见问题1:关于 “ MySQL Installer is running in Community mode ” 的解决办法
    窥见云技术未来大势,腾讯云Techo开发者大会即将在京召开
    揭秘国庆阅兵直播背后的黑科技,腾讯云提供技术支持
  • 原文地址:https://www.cnblogs.com/proverbs/p/2956685.html
Copyright © 2020-2023  润新知