有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个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;
第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为结束。我们假设在一开始所有的道路都是堵塞的。我们保证 C小于等于100000,信息条数小于等于100000。
对于每个查询,输出一个“Y”或“N”。
题解:JudgeOnline/upload/201604/sol(4).rar
题解:线段树维护连通性
对于相邻两个点维护6个信息。
需要注意的是查询的时候,该区间的r1,r2不连通,不一定r1,r2无法连通,所以需要考虑通过两边的区间使r1,r2连通的情况。
还有对于单点的修改,所有的值都要重新计算。
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>#include<cmath>#define N 100003using namespace std;int n;struct data { int l1,l2,h1,h2,r1,r2;//l1,l2,r1,r2是真实存在的,h1,h2每次更改都需要重新推 data() { l1=l2=h1=h2=r1=r2=0; }}tr[N*4],a[N];//l1表示左上角到右上角//l2表示左下角到右下角 //r1表示左上角到左下角 //r2表示右上角到右下角 //h1表示左上角到右下角 //h2表示左下角到右上角 data update(data a,data b){ data t; t.l1=max(t.l1,a.l1&b.l1); t.l1=max(t.l1,a.h1&b.h2); t.l2=max(t.l2,a.l2&b.l2); t.l2=max(t.l2,a.h2&b.h1); t.r1=a.r1; t.r1=max(t.r1,t.l1&t.l2&b.r2); t.r1=max(t.r1,a.l1&b.r1&a.l2); t.r2=b.r2; t.r2=max(t.r2,t.l1&t.l2&a.r1); t.r2=max(t.r2,b.l1&b.l2&a.r2); t.h1=max(t.h1,a.l1&b.h1); t.h1=max(t.h1,a.h1&b.l2); t.h2=max(t.h2,a.h2&b.l1); t.h2=max(t.h2,a.l2&b.h2); return t;}void pointchange(int now,int l,int r,int opt,int x,int val)//opt=1 l1;opt=2 l2; opt=3 r1;opt=4 r2;{ if (x==0) return; if (l==r) { tr[now].l1=a[l].l1; tr[now].l2=a[l].l2; tr[now].r1=a[l].r1; tr[now].r2=a[l].r2; tr[now].l1=max(tr[now].l1,tr[now].r1&tr[now].l2&tr[now].r2); tr[now].l2=max(tr[now].l2,tr[now].r1&tr[now].l1&tr[now].r2); tr[now].r1=max(tr[now].r1,tr[now].l1&tr[now].r2&tr[now].l2); tr[now].r2=max(tr[now].r2,tr[now].l1&tr[now].r1&tr[now].l2); tr[now].h1=max(tr[now].r1&tr[now].l2,tr[now].l1&tr[now].r2); tr[now].h2=max(tr[now].r1&tr[now].l1,tr[now].l2&tr[now].r2); return; } int mid=(l+r)/2; if (x<=mid) pointchange(now<<1,l,mid,opt,x,val); else pointchange(now<<1|1,mid+1,r,opt,x,val); tr[now]=update(tr[now<<1],tr[now<<1|1]); }data query(int now,int l,int r,int ll,int rr){ data t; if (rr<ll||!ll) return t; if (ll<=l&&r<=rr) return tr[now]; int mid=(l+r)/2; bool pd=false; if (ll<=mid) t=query(now<<1,l,mid,ll,rr),pd=true; if (rr>mid) { data a=query(now<<1|1,mid+1,r,ll,rr); if (pd) t=update(t,a); else t=a; } return t;}int main(){ freopen("a.in","r",stdin); freopen("my.out","w",stdout); scanf("%d",&n); while (true) { char s[10]; scanf("%s",s); int x,y,x0,y0; scanf("%d%d%d%d",&x0,&y0,&x,&y); if (y0>y) swap(x0,x),swap(y0,y); if (s[0]=='E') break; if(s[0]=='O'||s[0]=='C') { int opt=0; int t=0; data t1; if (s[0]=='O') t=1; if (x0==x&&x==1) opt=1,a[y0].l1=t,pointchange(1,1,n,1,y0,t); if (x0==x&&x==2) opt=2,a[y0].l2=t,pointchange(1,1,n,2,y0,t); if (y0==y){ a[y].r1=t,pointchange(1,1,n,3,y,t); a[y-1].r2=t,pointchange(1,1,n,4,y-1,t); } } else { int opt; data t,t1,t2; int pd=false; if (x==x0&&y==y0) { PRintf("Y/n"); continue; } if (x0==x&&x==1) { t1=query(1,1,n,1,y0-1); t2=query(1,1,n,y,n); t=query(1,1,n,y0,y-1),pd=t.l1; t.r1=max(t.r1,t1.r2); t.r2=max(t.r2,t2.r1); pd=max(pd,t.r1&t.l2&t.r2); } if (x0==x&&x==2){ t=query(1,1,n,y0,y-1),pd=t.l2; t1=query(1,1,n,1,y0-1); t2=query(1,1,n,y,n); t.r1=max(t.r1,t1.r2); t.r2=max(t.r2,t2.r1); pd=max(pd,t.r1&t.l1&t.r2); } if (x0==1&&x==2&&y!=y0) { t=query(1,1,n,y0,y-1),pd=t.h1; t1=query(1,1,n,1,y0-1); t2=query(1,1,n,y,n); t.r1=max(t.r1,t1.r2); t.r2=max(t.r2,t2.r1); pd=max(pd,t.r1&t.l2); pd=max(pd,t.r2&t.l1); pd=max(pd,t.r1&t.h2&t.r2); } if (x0==2&&x==1&&y!=y0) { t=query(1,1,n,y0,y-1),pd=t.h2; t1=query(1,1,n,1,y0-1); t2=query(1,1,n,y,n); t.r1=max(t.r1,t1.r2); t.r2=max(t.r2,t2.r1); pd=max(pd,t.r1&t.l1); pd=max(pd,t.r2&t.l2); pd=max(pd,t.r1&t.h1&t.r2); } if (x0!=x&&y==y0) { t1=query(1,1,n,1,y0-1); t2=query(1,1,n,y,n); pd=t1.r2|t2.r1; } if (pd) printf("Y/n"); else printf("N/n"); } }}
新闻热点
疑难解答