zoukankan      html  css  js  c++  java
  • Bzoj1018[SHOI2008]堵塞的交通traffic(线段树)

    这题需要维护连通性,看到有连接删除,很容易直接就想LCT了。然而这题点数20w操作10w,LCT卡常估计过不去。看到这个东西只有两行,考虑能否用魔改后的线性数据结构去维护。我想到了线段树。

    考虑如果两个点相连,能有几种情况。有一种是两个点直接经过中间的路径相连,这个满足合并性,很容易维护。然后就是某一个点(或两个点)从两边绕了一下,由上到下或由下到上,然后走中间了路径相连的情况。

    (借用官方的一张图)

    对于第二种情况,考虑它应该是是什么样子的。注意这张图总共就两行,那么这个东西一定是从上面一行走横着的边到某一个位置,走一条竖着的边,然后再到下面连续走横着的边。

    所以,我们对于某一个位置能否到达其对应位置,只需要维护其横向能到达的最远位置,以及这两个位置之间有没有纵向边即可。

    确定位置只需要维护横向连通性,然后线段树二分即可。

    横向连通性满足合并性,总向边可以用数量求和,均可以用线段树维护。

    于是此题得解。

    关于实现,我们定义每个区间保存一个Node,其中f[0/1][0/1]表示区间左边的上、下能否到区间右边的上下(0上1下),维护linked[0/1]表示区间(0上1下)是否左右全部联通,同时维护sum表示这个区间纵向边数量的和。

    对于每一个位置,维护ver表示是否有纵向边,hor[0/1]表示从位置i有没有到位置i+1的横向边(0上1下)。

    合并的话节点直接用左右状态判,和很容易转移。

    查询位置的线段树二分,无非就是先向上走再向下走,自行脑补一发即可(不会看代码)。

    最终判定的时候用了一下状压,仅能判定上面的点用1,仅能判定下面用2,如果上下联通,则均可判定,用3来表示。

    最后上代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<algorithm>
      5 #define debug cout
      6 using namespace std;
      7 const int maxn=1e5+1e2;
      8 
      9 int l[maxn<<3],r[maxn<<3],lson[maxn<<3],rson[maxn<<3],fa[maxn<<3];
     10 int linked[maxn<<3][2],ver[maxn],hor[maxn][2]; 
     11 int sum[maxn<<3];
     12 
     13 struct Node {
     14     int f[2][2];
     15     int* operator [] (const int &x) {
     16         return f[x];
     17     }
     18     Node() {
     19         memset(f,0,sizeof(f));
     20     }
     21 }ns[maxn<<3];
     22 int n,m,cnt;
     23 
     24 inline Node merge(int* h,Node a,Node b) {
     25     Node ret;
     26     ret.f[0][0] = ( a[0][0]&h[0]&b[0][0] ) | ( a[0][1]&h[1]&b[1][0] );
     27     ret.f[1][1] = ( a[1][1]&h[1]&b[1][1] ) | ( a[1][0]&h[0]&b[0][1] );
     28     ret.f[0][1] = ( a[0][0]&h[0]&b[0][1] ) | ( a[0][1]&h[1]&b[1][1] );
     29     ret.f[1][0] = ( a[1][1]&h[1]&b[1][0] ) | ( a[1][0]&h[0]&b[0][0] );
     30     return ret;
     31 }
     32 
     33 inline void build(int pos,int ll,int rr) {
     34     l[pos] = ll , r[pos] = rr;
     35     if( ll == rr ) {
     36         ns[pos][0][0] = ns[pos][1][1] = 1;
     37         linked[pos][0] = linked[pos][1] = 1;
     38         return;
     39     }
     40     const int mid = ( ll + rr ) >> 1;
     41     build(lson[pos]=++cnt,ll,mid);
     42     build(rson[pos]=++cnt,mid+1,rr);
     43     fa[lson[pos]] = fa[rson[pos]] = pos;
     44 }
     45 inline void update_ver(int pos,int tar,int sta) {
     46     if( tar < l[pos] || r[pos] < tar )
     47         return;
     48     if( l[pos] == r[pos] ) {
     49         sum[pos] = ver[tar] = sta;
     50         ns[pos][0][1] = ns[pos][1][0] = sta;
     51         return;
     52     }
     53     const int mid = ( l[pos] + r[pos] ) >> 1;
     54     update_ver(lson[pos],tar,sta);
     55     update_ver(rson[pos],tar,sta);
     56     ns[pos] = merge(hor[mid],ns[lson[pos]],ns[rson[pos]]);
     57     sum[pos] = sum[lson[pos]] + sum[rson[pos]]; // remember this
     58 }
     59 inline void update_hor(int pos,int tar,int at,int sta) {
     60     if( tar < l[pos] || r[pos] < tar )
     61         return;
     62     if( l[pos] == r[pos] ) {
     63         hor[tar][at] = sta;
     64         return;
     65     }
     66     const int mid = ( l[pos] + r[pos] ) >> 1;
     67     update_hor(lson[pos],tar,at,sta);
     68     update_hor(rson[pos],tar,at,sta);
     69     ns[pos] = merge(hor[mid],ns[lson[pos]],ns[rson[pos]]);
     70     linked[pos][0] = linked[lson[pos]][0] & hor[mid][0] & linked[rson[pos]][0],
     71     linked[pos][1] = linked[lson[pos]][1] & hor[mid][1] & linked[rson[pos]][1];
     72 }
     73 inline Node querymid(int pos,int ll,int rr) {
     74     if( !pos )
     75         exit(0);
     76     if( ll <= l[pos] && r[pos] <= rr )
     77         return ns[pos];
     78     const int mid = ( l[pos] + r[pos] ) >> 1;
     79     if( rr <= mid )
     80         return querymid(lson[pos],ll,rr);
     81     if( ll > mid )
     82         return querymid(rson[pos],ll,rr);
     83     return merge(hor[mid],querymid(lson[pos],ll,rr),querymid(rson[pos],ll,rr));
     84 }
     85 inline int queryver(int pos,int ll,int rr) {
     86     if( rr < l[pos] || r[pos] < ll )
     87         return 0;
     88     if( ll <= l[pos] && r[pos] <= rr )
     89         return sum[pos];
     90     return queryver(lson[pos],ll,rr) + queryver(rson[pos],ll,rr);
     91 }
     92 inline int downleft(int pos,int at) {
     93     if( l[pos] == r[pos] )
     94         return l[pos];
     95     const int mid = ( l[pos] + r[pos] ) >> 1;
     96     if( hor[mid][at] && linked[rson[pos]][at] )
     97         return downleft(lson[pos],at);
     98     return downleft(rson[pos],at);
     99 }
    100 inline int leftup(int pos,int at) {
    101     if( pos == 1 )
    102         return 1;
    103     if( pos == lson[fa[pos]] )
    104         return leftup(fa[pos],at);
    105     const int fmid = l[pos] - 1;
    106     if( hor[fmid][at] ) {
    107         if( linked[lson[fa[pos]]][at] )
    108             return leftup(fa[pos],at);
    109         return downleft(lson[fa[pos]],at);
    110     }
    111     return l[pos];
    112 }
    113 inline int downright(int pos,int at) {
    114     if( l[pos] == r[pos] )
    115         return r[pos];
    116     const int mid = ( l[pos] + r[pos] ) >> 1;
    117     if( hor[mid][at] && linked[lson[pos]][at] )
    118         return downright(rson[pos],at);
    119     return downright(lson[pos],at);
    120 }
    121 inline int rightup(int pos,int at) {
    122     if( pos == 1 )
    123         return n;
    124     if( pos == rson[fa[pos]] )
    125         return rightup(fa[pos],at);
    126     const int fmid = r[pos];
    127     if( hor[fmid][at] ) {
    128         if( linked[rson[fa[pos]]][at] )
    129             return rightup(fa[pos],at);
    130         return downright(rson[fa[pos]],at);
    131     }
    132     return r[pos];
    133 }
    134 inline int findpos(int pos,int tar) {
    135     while( l[pos] != r[pos] ) {
    136         const int mid = ( l[pos] + r[pos] ) >> 1;
    137         if( tar <= mid )
    138             pos = lson[pos];
    139         else
    140             pos = rson[pos];
    141     }
    142     return pos;
    143 }
    144 
    145 inline void solve_case(int x,int y,int xx,int yy) {
    146     int sta = y , stb = yy , ans = 0;
    147     const int mostl = max( leftup(findpos(1,x),0) , leftup(findpos(1,x),1) );
    148     const int mostr = min( rightup(findpos(1,xx),0) , rightup(findpos(1,xx),1) );
    149     if( queryver(1,mostl,x) )
    150         sta = 3;
    151     if( queryver(1,xx,mostr) )
    152         stb = 3;
    153     Node md = querymid(1,x,xx);
    154     for(int i=0;i<2;i++)
    155         for(int j=0;j<2;j++)
    156             if( ( sta & (1<<i) ) && ( stb & (1<<j) ) )
    157                 ans |= md[i][j];
    158     puts(ans?"Y":"N");
    159 }
    160 
    161 char com[10];
    162 int x,y,xx,yy;
    163 
    164 inline void explain() {
    165     int sta = *com == 'O';
    166     if( y == yy )
    167         update_hor(1,x,y-1,sta);
    168     else if( x == xx ) {
    169         update_ver(1,x,sta);
    170     }
    171 }
    172 
    173 int main() {
    174     scanf("%d",&n);
    175     build(cnt=1,1,n);
    176     int cc = 0;
    177     while( scanf("%s",com) == 1 && *com != 'E' ) {
    178         scanf("%d%d%d%d",&y,&x,&yy,&xx);
    179         if( x > xx )
    180             swap(x,xx) , swap(y,yy);
    181         if( *com == 'A' )
    182             solve_case(x,y,xx,yy);
    183         else
    184             explain();
    185     }
    186     
    187     return 0;
    188     
    189 }
  • 相关阅读:
    POJ1417 True Liars
    POJ2912 Rochambeau
    POJ3904 Sky Code
    [SDOI2016]排列计数
    POJ2947 Widget Factory
    HDU5015 233 Matrix
    Problem 2242. -- [SDOI2011]计算器
    POJ2480 Longge's problem
    Problem 2818. -- Gcd
    LA3510 Pixel Shuffle
  • 原文地址:https://www.cnblogs.com/Cmd2001/p/8127620.html
Copyright © 2011-2022 走看看