很久之前听泽神说过这道题,今天终于下定决心写了
维护两个横,两个竖,两个斜的连通性h[2],s[2],x[2]。转移如下表(a为左子树,b为右子树,t为目标子树)
查询时要考虑绕了一圈的情况,即[1,l][l,r][r,n]三个区间的连通性
最后竟然是close的时候把边赋成了1
1018: [SHOI2008]堵塞的交通traffic
Time Limit: 3 Sec Memory Limit: 162 MB
Submit: 2233 Solved: 695
[Submit][Status][Discuss]
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;
第一行只有一个整数C,表示网格的列数。接下来若干行,每行为一条交通信息,以单独的一行“Exit”作为结束。我们假设在一开始所有的道路都是堵塞的。 对30%测试数据,我们保证C小于等于1000,信息条数小于等于1000; 对100%测试数据,我们保证 C小于等于100000,信息条数小于等于100000。
对于每个查询,输出一个“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
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define md
#define ll long long
#define inf (int) 1e9
#define eps 1e-8
#define N 100010
using namespace std;
struct tree {int l,r; bool s[2],h[2],x[2];} tr[4*N];
tree T,left,right;
bool line[N],road[2][N];
void outit(tree a)
{
printf("%d %d S: %d %d H: %d %d X: %d %d\n",a.l,a.r,a.s[0],a.s[1],a.h[0],a.h[1],a.x[0],a.x[1]);
}
tree update(tree a,tree b)
{
tree t; t.l=a.l; t.r=b.r;
if (a.s[0]||line[a.l]) t.s[0]=1; else t.s[0]=0;
if (b.s[1]||line[b.r]) t.s[1]=1; else t.s[1]=0;
t.h[0]=t.h[1]=t.x[0]=t.x[1]=0;
if (a.h[0]&&road[0][a.r]) //ah0 r0-l0
{
if (b.s[0]&&a.h[1]&&road[1][a.r]) t.s[0]=1;
if (b.h[0]) t.h[0]=1;
if (b.x[0]) t.x[0]=1;
}
if (a.x[0]&&road[1][a.r])//ax0 r1-l1
{
if (b.x[1]) t.h[0]=1;
if (b.h[1]) t.x[0]=1;
}
if (a.h[1]&&road[1][a.r])//ah1 r1-l1
{
if (b.x[1]) t.x[1]=1;
if (b.h[1]) t.h[1]=1;
}
if (a.x[1]&&road[0][a.r])//ax1 r0-l0
{
if (b.h[0]) t.x[1]=1;
if (b.x[0]) t.h[1]=1;
}
if (a.s[1]&&b.h[0]&&b.h[1]&&road[0][a.r]&&road[1][a.r]) t.s[1]=1;
return t;
}
void build(int i,int l,int r)
{
tr[i].l=l; tr[i].r=r;
if (l==r) { tr[i].h[0]=tr[i].h[1]=1; return; }
int mid=(l+r)>>1;
build(2*i,l,mid); build(2*i+1,mid+1,r);
tr[i]=update(tr[2*i],tr[2*i+1]);
}
void newline(int i)
{
int pos=tr[i].l;
if (line[pos]) tr[i].s[0]=tr[i].s[1]=tr[i].x[0]=tr[i].x[1]=1;
else tr[i].s[0]=tr[i].s[1]=tr[i].x[0]=tr[i].x[1]=0;
tr[i].h[0]=tr[i].h[1]=1;
}
void modify(int i,int l,int r)
{
if (tr[i].l==tr[i].r) { newline(i); return;}
int mid=(tr[i].l+tr[i].r)>>1;
if (r<=mid) modify(2*i,l,r);
if (mid+1<=l) modify(2*i+1,l,r);
tr[i]=update(tr[2*i],tr[2*i+1]);
}
tree query(int i,int l,int r)
{
//printf("query: %d %d, now: %d L %d R %d\n",l,r,i,tr[i].l,tr[i].r);
if (l<=tr[i].l&&tr[i].r<=r) return tr[i];
int mid=(tr[i].l+tr[i].r)>>1;
if (r<=mid) return query(2*i,l,r);
if (mid+1<=l) return query(2*i+1,l,r);
return update(query(2*i,l,r),query(2*i+1,l,r));
}
int main()
{
int n; char st[10];
int x1,y1,x2,y2;
scanf("%d",&n);
build(1,1,n);
while (1)
{
scanf("%s",st);
if (st[0]=='O')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--; x2--;
if (y1>y2) { swap(x1,x2); swap(y1,y2); }
if (x1==x2)
{
road[x1][min(y1,y2)]=1;
modify(1,y1,y2);
}
else
{
line[y1]=1;
modify(1,y1,y2);
}
}
else if (st[0]=='C')
{
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--; x2--;
if (y1>y2) { swap(x1,x2); swap(y1,y2); }
if (x1==x2)
{
road[x1][min(y1,y2)]=0;
modify(1,y1,y2);
}
else
{
line[y1]=0;
modify(1,y1,y2);
}
}
else if (st[0]=='A')
{
bool ans=0;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
x1--; x2--;
if (y1>y2) { swap(x1,x2); swap(y1,y2); }
T=query(1,y1,y2),left=query(1,1,min(y1,y2)),right=query(1,max(y1,y2),n);
if (y1==y2)//同一列
{
ans=T.s[0];
if (left.s[1]||right.s[0]) ans|=1;
}
else
if (x1==x2) //同一行
{
ans=T.h[x1];
bool L=0,R=0;
if (left.s[1]) L=1;
if (right.s[0]) R=1;
if ((L&&T.x[x1^1])||(R&&T.x[x1])||(L&&R&&T.h[x1^1])) ans=1;
}
else //一上一下
{
ans=T.x[x1];
bool L=0,R=0;
if (left.s[1]) L=1;
if (right.s[0]) R=1;
if ((L&&T.h[x1^1])||(R&&T.h[x1])||(L&&R&&T.x[x1^1])) ans=1;
}
if (ans) printf("Y\n"); else printf("N\n");
}
else break;/*
if (st[0]!='A') continue;
printf("road:\n");
for (int i=1;i<=n;i++) printf(" %d %d \\",road[0][i],road[1][i]); printf("\n");
printf("T: "); outit(T);
for (int i=1;i<=15;i++) outit(tr[i]); printf("\n");*/
}
return 0;
}