• 【BZOJ】1018: [SHOI2008]堵塞的交通traffic


    http://www.lydsy.com/JudgeOnline/problem.php?id=1018

    题意:有2行,每行有c(c<=100000)个城市,则一共有c-1个格子,现在有q(q<=100000)个操作,操作Open和Close是将格子的四个角相邻的城市连边或删边,操作Ask是询问两个城市是否连通

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=100005;
    struct T { bool d[2][2], f[2]; T() { CC(d, 0); CC(f, 0); } }t[N<<2];
    int n, a[N][4], tot;
    #define lc x<<1
    #define rc x<<1|1
    #define lson l, mid, lc
    #define rson mid+1, r, rc
    
    void upd1(T &x, int pos=-1) {
    	static bool ok[4][4];
    	CC(ok, 0);
    	if(pos==-1) {
    		if(x.d[0][0]) ok[0][2]=ok[2][0]=1;
    		if(x.d[0][1]) ok[0][3]=ok[3][0]=1;
    		if(x.d[1][0]) ok[1][2]=ok[2][1]=1;
    		if(x.d[1][1]) ok[1][3]=ok[3][1]=1;
    		if(x.f[0]) ok[0][1]=ok[1][0]=1;
    		if(x.f[1]) ok[2][3]=ok[3][2]=1;
    	}
    	else {
    		CC(x.d, 0);
    		CC(x.f, 0);
    		if(a[pos][0]) ok[0][2]=ok[2][0]=1;
    		if(a[pos][1]) ok[0][1]=ok[1][0]=1;
    		if(a[pos][2]) ok[1][3]=ok[3][1]=1;
    		if(a[pos][3]) ok[3][2]=ok[2][3]=1;
    	}
    	rep(i, 4) ok[i][i]=1;
    	rep(k, 4) rep(i, 4) if(ok[i][k]) rep(j, 4) if(ok[k][j]) ok[i][j]=1;
    	if(ok[0][1]) x.f[0]=1;
    	if(ok[0][2]) x.d[0][0]=1;
    	if(ok[0][3]) x.d[0][1]=1;
    	if(ok[2][3]) x.f[1]=1;
    	if(ok[1][2]) x.d[1][0]=1;
    	if(ok[1][3]) x.d[1][1]=1;
    }
    void pushup(T &x, T &l, T &r) {
    	x.d[0][0]=(l.d[0][0]&&r.d[0][0]) || (l.d[0][1]&&r.d[1][0]);
    	x.d[0][1]=(l.d[0][0]&&r.d[0][1]) || (l.d[0][1]&&r.d[1][1]);
    	x.d[1][0]=(l.d[1][0]&&r.d[0][0]) || (l.d[1][1]&&r.d[1][0]);
    	x.d[1][1]=(l.d[1][0]&&r.d[0][1]) || (l.d[1][1]&&r.d[1][1]);
    	x.f[0]=l.f[0] || (l.d[0][0]&&r.f[0]&&l.d[1][1]);
    	x.f[1]=r.f[1] || (r.d[0][0]&&l.f[1]&&r.d[1][1]);
    }
    void update(int pos, int l=1, int r=tot, int x=1) {
    	if(l==r) { upd1(t[x], pos); return; }
    	int mid=(l+r)>>1;
    	if(pos<=mid) update(pos, lson);
    	else update(pos, rson);
    	pushup(t[x], t[lc], t[rc]);
    }
    void ask(int L, int R, T &ret, int l=1, int r=tot, int x=1) {
    	if(L<=l && r<=R) { memcpy(ret.d, t[x].d, sizeof(ret.d)); memcpy(ret.f, t[x].f, sizeof(ret.f)); return; }
    	int mid=(l+r)>>1;
    	if(R<=mid) { ask(L, R, ret, lson); return; }
    	if(mid<L) { ask(L, R, ret, rson); return; }
    	T t1, t2;
    	ask(L, R, t1, lson);
    	ask(L, R, t2, rson);
    	pushup(ret, t1, t2);
    }
    void change(int x1, int y1, int x2, int y2, int f) {
    	if(y1==y2) {
    		if(y1==n) {
    			a[y1-1][3]=f;
    			update(y1-1);
    		}
    		else if(y1==1) {
    			a[y1][1]=f;
    			update(y1);
    		}
    		else {
    			a[y1-1][3]=f;
    			a[y1][1]=f;
    			update(y1-1);
    			update(y1);
    		}
    	}
    	else {
    		if(x1==0) a[y1][0]=f;
    		if(x1==1) a[y1][2]=f;
    		update(y1);
    	}
    	// T tt;
    	// ask(1, 1, tt); dbg(tt.d[0][0]); dbg(tt.d[0][1]); dbg(tt.d[1][0]); dbg(tt.d[1][1]); dbg(tt.f[0]); dbg(tt.f[1]);
    	// dbg(a[1][0]); dbg(a[1][3]);
    }
    void ask(int x1, int y1, int x2, int y2) {
    	if(x1==x2 && y1==y2) { puts("Y"); return; }
    	T l, r, mid;
    	if(y1==y2) {
    		if(y1==n) {
    			ask(1, tot, mid);
    			if(mid.f[1]) puts("Y");
    			else puts("N");
    		}
    		else if(y1==1) {
    			ask(1, tot, mid);
    			if(mid.f[0]) puts("Y");
    			else puts("N");
    		}
    		else {
    			ask(1, y1-1, l);
    			ask(y1, tot, r);
    			if(l.f[1] || r.f[0]) puts("Y");
    			else puts("N");
    		}
    	}
    	else {
    		if(y1-1>=1) ask(1, y1-1, l);
    		if(y2<=tot) ask(y2, tot, r);
    		ask(y1, y2-1, mid);
    		if(mid.d[x1][x2]) { puts("Y"); return; }
    		if(y1-1>=1 && l.f[1]) mid.f[0]=1;
    		if(y2<=tot && r.f[0]) mid.f[1]=1;
    		upd1(mid);
    		if(mid.d[x1][x2]) puts("Y");
    		else puts("N");
    	}
    }
    char s[10];
    int main() {
    	read(n); tot=n-1;
    	while(scanf("%s", s), s[0]!='E') {
    		int x1=getint(), y1=getint(), x2=getint(), y2=getint(); --x1; --x2;
    		if(y1>y2) swap(x1, x2), swap(y1, y2);
    		if(s[0]=='O') change(x1, y1, x2, y2, 1);
    		else if(s[0]=='C') change(x1, y1, x2, y2, 0);
    		else ask(x1, y1, x2, y2);
    	}
    	return 0;
    }
    

      


    这题有很大可以吐槽的地方!!!!!!!!!!!!!!!!!!!!!!!!!!

    首先这是一个坑,现在才来填平了....很早以前写的时候自己随便yy了一个类似lct一样的搞法(用并查集搞的lct...虽然没有路径压缩)交上去wa了...因为我是将整个图分层然后乱搞....

    那时候看了一下题解发现是很神的线段树....然后敲了一下自己yy不过来了就放弃了....

    然后之后某次我想填掉这个坑...可是按照自己yy的做发现不对于是又放弃...

    然后是昨晚上我又来做QAQ发现其实挺好想的...就是维护一下连通嘛blabla的..于是愉快地1h吧不到敲好且过了样例且静态查错了下....竟然wa了QAQ于是造数据和暴力对拍....小数据全过.....于是找标程对拍....好不容易终于拍出了一组数据....可是.....这是n=2000的数据能调?于是返回到静态查错的状态来...可是似乎很累的原因?我就一直盯着屏幕和纸看呀看...输出调试拍呀拍...果然还是太弱了...拍到凌晨还没搞定....4h已废(这个伟大的故事告诉我们状态不好的时候不要想题QAQ更不要调试.............

    果然是太弱了....于是今天中午来填坑(因为向root要到了数据...先评测了下...80分........于是再静态查了一下..立马发现了sb错......(果然还是要冷静+有精力才能肉眼拍完码农题啊QAQ)然后就a了》。。。

    果然还是太弱....

    题解:因为只有两行,因此状态可以设计为每个格子,所以只有c-1个格子(后边将c-1看做n),首先来分析只有一个格子的情况。显然要维护4个城市之间的连通性我直接floyd.....考虑多个格子连在一起的情况...如果我们要求[l, r]的城市的连通性(即[l, r-1]的格子,假设格子编号从1开始从左向右),那么可以用点什么东西维护一下整个区间的格子,则答案就是整个区间边界的4个点的连通性....发现了是不是都很相似,即求多个格子和一个格子都是取边界的4个点判断....而[l, r-1]是可以通过合并出来的...于是上线段树...orz(反正我是没yy出来线段树)即,对于[l, r]的格子(这个区间不是上边那个),我们假设有了中间一个点mid,则一定可以通过知道[l, mid], [mid+1, r]的连通性而推出[l, r]的连通性..(自己手推...)这样问题得到解决...

    可是如果仅仅是向上边那样只找[l, r]的连通性来回答询问是不够的....因为可能[l, r]的左边界和右边界在[l, r]这个区间是没有边或是不连通的...但是可能在<=l的区间能找出一条路径使得l的左边界连通,所以我们再查询[1, l-1],看看l-1这个格子的右边界是否连通就能知道l这个格子的左边界了...r同理.....

    最后提示一点,也就是我的sb错,千万要注意序号....就是城市与格子序号之间的关系...即第x列格子对应的格子可能有x-1和x这个格子..

  • 相关阅读:
    读《构建之法》阅读与思考
    软工沉浮沉沉沉沉沉沉…记事
    四则运算截图and代码
    2016012000郭慕然+散列函数的应用及其安全性
    结对作业之四则运算网页版
    阅读《构建执法》第四章及第十七章有感
    2016012000小学四则运算练习软件项目报告
    有关读《构建之法》的部分思考与疑问
    遇见·软件
    我的——今日学习内容
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4208196.html
Copyright © 2020-2023  润新知