• [SHOI2008]堵塞的交通


    Description

      有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可
    以被看成是一个2行C列的矩形网格,网格上的每个点代表一个城市,相邻的城市之间有一条道路,所以总共有2C个
    城市和3C-2条道路。 小人国的交通状况非常槽糕。有的时候由于交通堵塞,两座城市之间的道路会变得不连通,
    直到拥堵解决,道路才会恢复畅通。初来咋到的你决心毛遂自荐到交通部某份差事,部长听说你来自一个科技高度
    发达的世界,喜出望外地要求你编写一个查询应答系统,以挽救已经病入膏肓的小人国交通系统。 小人国的交通
    部将提供一些交通信息给你,你的任务是根据当前的交通情况回答查询的问题。交通信息可以分为以下几种格式:
    Close r1 c1 r2 c2:相邻的两座城市(r1,c1)和(r2,c2)之间的道路被堵塞了;Open r1 c1 r2 c2:相邻的两座城
    市(r1,c1)和(r2,c2)之间的道路被疏通了;Ask r1 c1 r2 c2:询问城市(r1,c1)和(r2,c2)是否连通。如果存在一
    条路径使得这两条城市连通,则返回Y,否则返回N;

    Input

      第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为
    结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。

    Output

      对于每个查询,输出一个“Y”或“N”。

    Sample Input

    2
    Open 1 1 1 2
    Open 1 2 2 2
    Ask 1 1 2 2
    Ask 2 1 2 2
    Exit

    Sample Output

    Y
    N
    线段树中区间[l, r]存储(1, l)、(2, l)、(1, r)、(2, r)四个点两两间的连通性,总共有6种
    合并:
    区间合并的六种情况
    横向边用2个数组ru和rd保存,用于合并,对于6个连通性,一一合并
    修改:
    修改横向边时,修改ru和rd数组,然后从下往上合并
    修改纵向边时,修改该区间内四种状态,然后从下往上合并
    查询:
    优于可能存在这样的情况:
    左右绕的示例
    所以[1,c1],[c1,c2],[c2,n]的连通情况都要算出来
    然后根据r1,r2判断就行了
      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #include<cmath>
      6 using namespace std;
      7 struct Data
      8 {
      9   bool luru,lurd,luld,ldru,ldrd,rurd;
     10 }c[400001];
     11 bool ru[200001],rd[200001];
     12 int n;
     13 char s[21];
     14 Data merge(Data dl,Data dr,int mid)
     15 {
     16   Data dm;
     17   dm.luru=(dl.luru&ru[mid]&dr.luru)||(dl.lurd&rd[mid]&dr.ldru);
     18   dm.lurd=(dl.luru&ru[mid]&dr.lurd)||(dl.lurd&rd[mid]&dr.ldrd);
     19   dm.luld=(dl.luld)||(ru[mid]&&rd[mid]&&dl.luru&&dl.ldrd&&dr.luld);
     20   dm.ldru=(dl.ldru&&ru[mid]&&dr.luru)||(dl.ldrd&&rd[mid]&&dr.ldru);
     21   dm.ldrd=(dl.ldrd&&rd[mid]&&dr.ldrd)||(dl.ldru&&ru[mid]&&dr.lurd);
     22   dm.rurd=(dr.rurd)||(ru[mid]&&rd[mid]&&dr.luru&&dr.ldrd&&dl.rurd);
     23   return dm;
     24 }
     25 void update1(int rt,int l,int r,int x,bool up,bool k)
     26 {
     27   if (l==r)
     28     {
     29       if (up) ru[x]=k;
     30       else rd[x]=k;
     31       return;
     32     }
     33   int mid=(l+r)>>1;
     34   if (x<=mid) update1(rt<<1,l,mid,x,up,k);
     35   else update1(rt<<1|1,mid+1,r,x,up,k);
     36   c[rt]=merge(c[rt<<1],c[rt<<1|1],mid);
     37 }
     38 void update2(int rt,int l,int r,int x,bool k)
     39 {
     40   if (l==r)
     41     {
     42       c[rt].luld=c[rt].rurd=c[rt].lurd=c[rt].ldru=k;
     43       return;
     44     }
     45   int mid=(l+r)>>1;
     46   if (x<=mid) update2(rt<<1,l,mid,x,k);
     47   else update2(rt<<1|1,mid+1,r,x,k);
     48   c[rt]=merge(c[rt<<1],c[rt<<1|1],mid);
     49 }
     50 Data query(int rt,int l,int r,int L,int R)
     51 {
     52   if (l==L&&r==R)
     53     {
     54       return c[rt];
     55     }
     56   int mid=(l+r)>>1;
     57   if (L>mid) return query(rt<<1|1,mid+1,r,L,R);
     58   else if (R<=mid) return query(rt<<1,l,mid,L,R);
     59   else
     60     {
     61       return merge(query(rt<<1,l,mid,L,mid),query(rt<<1|1,mid+1,r,mid+1,R),mid);
     62     }
     63 }
     64 void build(int rt,int l,int r)
     65 {
     66   if (l==r)
     67     {
     68       c[rt].luru=1;c[rt].ldrd=1;
     69       return;
     70     }
     71   int mid=(l+r)>>1;
     72   build(rt<<1,l,mid);
     73   build(rt<<1|1,mid+1,r);
     74 }
     75 int main()
     76 {int i,r1,r2,c1,c2;
     77   cin>>n;
     78   build(1,1,n);
     79   for (i=1;i<n;i++)
     80     ru[i]=rd[i]=0;
     81   while (1)
     82     {
     83       scanf("%s",s);
     84       scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
     85       if (c1>c2) swap(c1,c2),swap(r1,r2);
     86       if (s[0]=='E') break;
     87       if (s[0]=='O')
     88     {
     89       if (r1==r2)
     90         update1(1,1,n,c1,r1==1,1);
     91       else update2(1,1,n,c2,1);
     92     }
     93       else if (s[0]=='C')
     94     {
     95       if (r1==r2)
     96         update1(1,1,n,c1,r1==1,0);
     97       else update2(1,1,n,c2,0);
     98     }
     99       else
    100     {
    101       Data dm=query(1,1,n,c1,c2),dl=query(1,1,n,1,c1),dr=query(1,1,n,c2,n);
    102       if (r1==1&&r2==1)
    103         {
    104           bool b1=dm.luru;
    105           bool b2=dl.rurd&dm.ldru;
    106           bool b3=dm.lurd&dr.luld;
    107           bool b4=dl.rurd&dm.ldrd&dr.luld;
    108           if (b1||b2||b3||b4) printf("Y
    ");
    109           else printf("N
    ");
    110         }
    111       else if (r1==2&&r2==2)
    112         {
    113           bool b1=dm.ldrd;
    114           bool b2=dl.rurd&dm.lurd;
    115           bool b3=dm.ldru&dr.luld;
    116           bool b4=dl.rurd&dm.luru&dr.luld;
    117           if (b1||b2||b3||b4) printf("Y
    ");
    118           else printf("N
    ");
    119         }
    120       else if (r1==1&&r2==2)
    121         {
    122           bool b1=dm.lurd;
    123           bool b2=dl.rurd&dm.ldrd;
    124           bool b3=dm.luru&dr.luld;
    125           bool b4=dl.rurd&dm.ldru&dr.luld;
    126           if (b1||b2||b3||b4) printf("Y
    ");
    127           else printf("N
    ");
    128         }
    129       else if (r1==2&&r2==1)
    130         {
    131           bool b1=dm.ldru;
    132           bool b2=dl.rurd&dm.luru;
    133           bool b3=dm.ldrd&dr.luld;
    134           bool b4=dl.rurd&dm.lurd&dr.luld;
    135           if (b1||b2||b3||b4) printf("Y
    ");
    136           else printf("N
    ");
    137         }
    138     }
    139     }
    140 }

    左右绕的示例

  • 相关阅读:
    Spring 定时任务
    JSOUP 爬虫
    Google 翻译(中英,英中)
    linux mysql 卸载与安装及配置命令
    2.logback+slf4j+janino 配置项目的日志输出
    DW3 消息推送
    JQuery 常用知识
    intellij idea 2016.3.5 控制台取消行数限制
    1.搭建Maven 多模块应用 --Intellij IDEA 2016.3.5
    JSON 解析工具的封装(Java)
  • 原文地址:https://www.cnblogs.com/Y-E-T-I/p/8465521.html
Copyright © 2020-2023  润新知