码迷,mamicode.com
首页 > 其他好文 > 详细

[SHOI2008]堵塞的交通

时间:2018-11-06 21:25:21      阅读:169      评论:0      收藏:0      [点我收藏+]

标签:复杂   用途   new   swap   ref   上下   变量   cpp   lin   

题意

Here

思考

一道很好的线段树题 \(&&\) 一道很毒瘤的码农题

一开始完全没想到用线段树来维护这种网格的连通性,后来看题解之后发现实在是妙啊……(满足区间可合并性)

线段树维护的是一段区间的四个端点间两两的连通信息,六个变量,合并时由于要考虑两块是否可合并,还得维护区间中间两点是否连通,两个变量。所以总共是八个变量,合并的时候分类讨论有些复杂,具体见代码。

代码

#include<bits/stdc++.h>
#define ls(pos) pos << 1
#define rs(pos) pos << 1 | 1
using namespace std;
const int N = 200020;
int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}
    while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
    return x * f;
}
struct node{
    int l, r, u, d, p, q, mid1, mid2;
};
namespace Seg{
    int l[N << 2], r[N << 2], u[N << 2], d[N << 2], p[N << 2], q[N << 2], mid1[N << 2], mid2[N << 2];
    ///l左侧上下 r右侧上下 u上 d下 p左上右下 q左下右上 mid1第一行中间是否联通 mid2第二行…
    void pushup(int pos){
        l[pos] = l[ls(pos)] || (u[ls(pos)] && mid1[pos] && l[rs(pos)] && mid2[pos] && d[ls(pos)]);
        r[pos] = r[rs(pos)] || (u[rs(pos)] && mid1[pos] && r[ls(pos)] && mid2[pos] && d[rs(pos)]);
        u[pos] = (u[ls(pos)] && u[rs(pos)] && mid1[pos]) || (p[ls(pos)] && mid2[pos] && q[rs(pos)]);
        d[pos] = (d[ls(pos)] && d[rs(pos)] && mid2[pos]) || (q[ls(pos)] && mid1[pos] && p[rs(pos)]);
        p[pos] = (p[ls(pos)] && mid2[pos] && d[rs(pos)]) || (u[ls(pos)] && mid1[pos] && p[rs(pos)]);
        q[pos] = (q[ls(pos)] && mid1[pos] && u[rs(pos)]) || (d[ls(pos)] && mid2[pos] && q[rs(pos)]);
    }
    void build(int pos, int ll, int rr){
        if(ll == rr){
            mid1[pos] = mid2[pos] = u[pos] = d[pos] = 1;
            return ;
        }
        int mid = (ll + rr) >> 1;
        build(ls(pos), ll, mid);
        build(rs(pos), mid+1, rr);
    }
    void modify(int pos, int ll, int rr, int x, int v){///竖
        if(ll == rr){
            l[pos] = r[pos] = p[pos] = q[pos] = v;
            return ;
        }
        int mid = (ll + rr) >> 1;
        if(x <= mid) modify(ls(pos), ll, mid, x, v);
        else modify(rs(pos), mid+1, rr, x, v);
        pushup(pos);
    }
    void modify2(int pos, int ll, int rr, int op, int x, int v){///横
        int mid = (ll + rr) >> 1;
        if(mid == x){
            if(op == 1) mid1[pos] = v;
            else mid2[pos] = v;
            pushup(pos);
            return ;
        }
        if(x <= mid) modify2(ls(pos), ll, mid, op, x, v);
        else modify2(rs(pos), mid+1, rr, op, x, v);
        pushup(pos);
    }
    node query(int pos, int ll, int rr, int x, int y){
        if(x <= ll && rr <= y){
            node ans = (node){l[pos], r[pos], u[pos], d[pos], p[pos], q[pos], mid1[pos], mid2[pos]};
            return ans;
        }
        int mid = (ll + rr) >> 1;
        if(y <= mid) return query(ls(pos), ll, mid, x, y);
        else if(x > mid) return query(rs(pos), mid+1, rr, x, y);
        else{
            node ans = (node){l[pos], r[pos], u[pos], d[pos], p[pos], q[pos], mid1[pos], mid2[pos]};
            node ansl = query(ls(pos), ll, mid, x, y), ansr = query(rs(pos), mid+1, rr, x, y);
            ans.l = ansl.l || (ansl.u && ans.mid1 && ansr.l && ans.mid2 && ansl.d);
            ans.r = ansr.r || (ansr.u && ans.mid1 && ansl.r && ans.mid2 && ansr.d);
            ans.u = (ansl.u && ansr.u && ans.mid1) || (ansl.p && ans.mid2 && ansr.q);
            ans.d = (ansl.d && ansr.d && ans.mid2) || (ansl.q && ans.mid1 && ansr.p);
            ans.p = (ansl.p && ans.mid2 && ansr.d) || (ansl.u && ans.mid1 && ansr.p);
            ans.q = (ansl.q && ans.mid1 && ansr.u) || (ansl.d && ans.mid2 && ansr.q);
            return ans;
        }
    }
}
using namespace Seg;
int n;
int main(){
    n = read();
    build(1, 1, n);
    while(233){
        char op[20]; cin >> op + 1;
        if(op[1] == ‘E‘) break;
        int r1 = read(), c1 = read(), r2 = read(), c2 = read();
        if(c1 > c2) swap(c1, c2), swap(r1, r2);
        if(op[1] == ‘O‘){
            if(c1 == c2) modify(1, 1, n, c1, 1);
            else modify2(1, 1, n, r1, c1, 1);
        }
        if(op[1] == ‘C‘){
            if(c1 == c2) modify(1, 1, n, c1, 0);
            else modify2(1, 1, n, r1, c1, 0);
        }
        if(op[1] == ‘A‘){
            int ans = 0;
            node l = query(1, 1, n, 1, c1), mid = query(1, 1, n, c1, c2), r = query(1, 1, n, c2, n);
            if(r1 == 1 && r2 == 1) ans = mid.u || (l.r && mid.q) || (r.l && mid.p) || (l.r && mid.d && r.l);
            if(r1 == 2 && r2 == 2) ans = mid.d || (l.r && mid.p) || (r.l && mid.q) || (l.r && mid.u && r.l);
            if(r1 == 1 && r2 == 2) ans = mid.p || (l.r && mid.d) || (r.l && mid.u) || (l.r && mid.q && r.l);
            if(r1 == 2 && r2 == 1) ans = mid.q || (l.r && mid.u) || (r.l && mid.d) || (l.r && mid.p && r.l);
            if(ans) puts("Y");
            else puts("N");
        }
    }
    return 0;
}

总结

这题细节很多,也比较锻炼码力吧,我觉得以后遇到这种题还是要有足够的把握才写正解,写正解的话也要注意:把变量的用途尽量注释出来,写程序时多多检查,多调试,保证每步要正确,不然查错的时候??

[SHOI2008]堵塞的交通

标签:复杂   用途   new   swap   ref   上下   变量   cpp   lin   

原文地址:https://www.cnblogs.com/alecli/p/9918040.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!