=== ===
Put here Portal
=== ===
Title Solution
This problem is poisonous... It is said that zyf2000 wrote the 7k code result T and then wrote another...
Consider treating each small rectangle as an element in a sequence, and then maintaining six quantities for each interval, as shown in the following figure (mama this terrible resolution):
The meaning of each element in the segment tree is whether there is an x0 (or other number) equivalent path in the rectangular sequence governed by the current node. For example, if the element representing y0 in the segment tree is true, there is a path from the upper left corner of the interval to the lower left corner of the interval. And notice that this thing can be merged, that is to say, if a sequence of small rectangles is bounded by mid (here mid means a vertical line of two points instead of a small rectangle) and divided into two parts, from the left end of the sequence to the right end or from the right end to the left end of the sequence will inevitably pass through the mid line, then the left and right subtrees can be merged to get the father's value. .
For example, if we want to recurse the x0 of the current node, there are two ways: one is through the upper end of the mid segment, the other is through the lower end of the mid segment. In the first case, the x0 of both left and right subtrees is required to be connected, and in the second case, the z0 of the left subtree and the z1 of the right subtree are required to be connected.
If it is a leaf node of a line segment tree, you can only enumerate each case manually... For example, if the graph above requires x0 interconnection, one way is that the road of AB is directly connected. Another way is to go y0 first and then z1, or y0 - > X1 - > y1, or Z0 - > y1, or Z0 - > X1 - > z1. Other parts of the situation is super many ah must think about all...
Note that because the line segment tree array represents connectivity, and sometimes changes in Close operations can be cumbersome. For example, if three edges x0, y0 and x1 are connected in a unit rectangle, then all six fields will be set to true through the UPD process, because any two of the four points can reach each other. If the y0 side is removed next, it is reasonable that only x0 and x1 can be connected at this time, but after removing y0 from the segment tree, the remaining five domains are all true, the program will understand that there are five edges connected, and then the modification of y0 will be covered. So another array is created to store the original edges without recursion, which are maintained in the modification process.
Query operation is also very troublesome. Because the connectivity of the [x.y] segment may not only be related to the path of [x.y], it may go somewhere else to circle and come back. Simply speaking, it can be directly arrived at, it can also turn out the sequence from the left, it can also turn out the sequence from the right, it can also turn out the sequence from left to right, and it can turn out the sequence at the same time. There are at most four different ways of traveling on a single path, which should be taken into account. For example, if the x0 of a rectangular sequence [left... right] is to be connected, one way is to go directly from the upper left corner to the upper right corner within the sequence. One way is to go first from the upper right corner of the interval [1... left - 1] to the lower right corner, that is, to go along the y1 side, then from the x1 side of [left... right], and then from the y1 side of [left... right] to the end, and the other way is to follow the [left... right... right] side first. ] Go along the y0 side of [right+1.c], then go along the y0 side of [right+1.c], and so on.
Anyway, the problem is poisonous...
Code
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int c,cnt;
char o[10];
struct tree{
bool b[3][2];
tree(){memset(b,false,sizeof(b));}
void UPD(tree g);
}t[500010],ans,org[100010];
void tree::UPD(tree g){//Enumeration of Connection Status of Unit Rectangles by Edge Information
b[0][0]=g.b[0][0]||(g.b[1][0]&&g.b[2][1])||(g.b[1][0]&&g.b[0][1]&&g.b[1][1])||(g.b[2][0]&&g.b[1][1])||(g.b[2][0]&&g.b[0][1]&&g.b[2][1]);
b[0][1]=g.b[0][1]||(g.b[1][0]&&g.b[2][0])||(g.b[1][0]&&g.b[0][0]&&g.b[1][1])||(g.b[2][1]&&g.b[1][1])||(g.b[2][1]&&g.b[0][0]&&g.b[2][0]);
b[1][0]=g.b[1][0]||(g.b[2][0]&&g.b[0][1])||(g.b[2][0]&&g.b[1][1]&&g.b[2][1])||(g.b[0][0]&&g.b[2][1])||(g.b[0][0]&&g.b[1][1]&&g.b[0][1]);
b[1][1]=g.b[1][1]||(g.b[2][1]&&g.b[0][1])||(g.b[2][1]&&g.b[1][0]&&g.b[2][0])||(g.b[0][0]&&g.b[2][0])||(g.b[0][0]&&g.b[1][0]&&g.b[0][1]);
b[2][0]=g.b[2][0]||(g.b[0][0]&&g.b[1][1])||(g.b[0][0]&&g.b[2][1]&&g.b[0][1])||(g.b[1][0]&&g.b[0][1])||(g.b[1][0]&&g.b[2][1]&&g.b[1][1]);
b[2][1]=g.b[2][1]||(g.b[1][0]&&g.b[0][0])||(g.b[1][0]&&g.b[2][0]&&g.b[1][1])||(g.b[0][1]&&g.b[1][1])||(g.b[0][1]&&g.b[2][0]&&g.b[0][0]);
}
void update(tree &tr,tree lc,tree rc)
{
tr.b[0][0]=(lc.b[0][0]&&rc.b[0][0])||(lc.b[2][0]&&rc.b[2][1]);
tr.b[0][1]=(lc.b[0][1]&&rc.b[0][1])||(lc.b[2][1]&&rc.b[2][0]);
tr.b[1][0]=lc.b[1][0]||(lc.b[0][0]&&lc.b[0][1]&&rc.b[1][0]);
tr.b[1][1]=rc.b[1][1]||(rc.b[0][0]&&rc.b[0][1]&&lc.b[1][1]);
tr.b[2][0]=(lc.b[0][0]&&rc.b[2][0])||(lc.b[2][0]&&rc.b[0][1]);
tr.b[2][1]=(lc.b[2][1]&&rc.b[0][0])||(lc.b[0][1]&&rc.b[2][1]);
}
void change(int i,int l,int r,int u,int x,int y,int v){
if (l==r){
org[l].b[x][y]=v;//Note: Only the org array is modified directly
t[i].UPD(org[l]);
return;
}
int mid=(l+r)>>1;
if (u<=mid)
change(i<<1,l,mid,u,x,y,v);
else change((i<<1)+1,mid+1,r,u,x,y,v);
update(t[i],t[i<<1],t[(i<<1)+1]);
}
tree ask(int i,int l,int r,int left,int right){
tree ans[4];
int cnt=0;
if ((left<=l)&&(right>=r))
return t[i];
int mid=(l+r)>>1;
if (left<=mid){
ans[2]=ask(i<<1,l,mid,left,right);cnt+=1;
}//Note the use of cnt variables to record access information
if (right>mid){
ans[3]=ask((i<<1)+1,mid+1,r,left,right);cnt+=2;
}
if (cnt==3){//Merge only if both half of the intervals have been visited
update(ans[1],ans[2],ans[3]);
return ans[1];
}else return ans[cnt+1];
}
bool query(int left,int right,int x,int y){
ans=ask(1,1,c,left,right);
return ans.b[x][y];
}
int main()
{
scanf("%d",&c);--c;
scanf("%s",o);
while (o[0]!='E'){
int r1,c1,r2,c2;
scanf("%d%d%d%d",&r1,&c1,&r2,&c2);
if ((o[0]=='O')||(o[0]=='C')){
int dlt,x,y,num=min(c1,c2);
if ((r1==1)&&(r2==1)) x=y=0;
if ((r1==2)&&(r2==2))
{x=0;y=1;}//If it's a horizontal edge, find the number you want to modify
if (o[0]=='O') dlt=1;
else dlt=0;
if (c1!=c2)
change(1,1,c,num,x,y,dlt);
if (c1==c2)
if (c1==c+1)
change(1,1,c,c,1,1,dlt);
else if (c1==1)
change(1,1,c,1,1,0,dlt);
else{//Note that when you modify a vertical edge, you change two rectangles, y1 and y0 domains, respectively.
change(1,1,c,c1,1,0,dlt);
change(1,1,c,c1-1,1,1,dlt);
}
}else{
if ((r1==r2)&&(c1==c2)){
printf("Y\n");
scanf("%s",o);
continue;
}
bool can=0;
int x;
if (r1==r2){
if (c1>c2) swap(c1,c2);//Make sure the number is small before the
if (r1==1) x=0;
else x=1;
if (c1==1&&c2==c+1)
can=query(1,c,0,x);
else//Special judgment of boundary conditions to prevent cross-border
if (c1==1) can=query(c1,c2-1,0,x)||(query(c1,c2-1,2,x)&&query(c2,c,1,0));
else//If the left endpoint is1,Then you can only turn out from the right, the same as the others.
if (c2==c+1) can=query(c1,c2-1,0,x)||(query(c1,c2-1,2,x^1)&&query(1,c1-1,1,1));
else{
bool can1,can2,can3;
can1=query(c1,c2-1,0,x)||(query(1,c1-1,1,1)&&query(c1,c2-1,2,x^1));
can2=query(c2,c,1,0)&&query(c1,c2-1,2,x);
can3=query(1,c1-1,1,1)&&query(c1,c2-1,0,x^1)&&query(c2,c,1,0);
can=can1||can2||can3;
}
}else
if (c1==c2)
if (c1==1) can=query(1,c,1,0);
else
if (c1==c+1) can=query(1,c,1,1);
else can=query(1,c1-1,1,1)||query(c1,c,1,0);
else{
if (c1>c2){
swap(r1,r2);swap(c1,c2);
}
if (r1<r2) x=0;
else x=1;
if (c1==1&&c2==c+1)
can=query(1,c,2,x);
else
if (c1==1) can=query(c1,c2-1,2,x)||(query(c1,c2-1,0,x)&&query(c2,c,1,0));
else
if (c2==c+1) can=query(c1,c2-1,2,x)||(query(c1,c2-1,0,x^1)&&query(1,c1-1,1,1));
else{
bool can1,can2,can3;
can1=query(c1,c2-1,2,x)||(query(c1,c2-1,0,x)&&query(c2,c,1,0));
can2=query(c1,c2-1,0,x^1)&&query(1,c1-1,1,1);
can3=query(1,c1-1,1,1)&&query(c1,c2-1,2,x^1)&&query(c2,c,1,0);
can=can1||can2||can3;
}
}
printf("%c\n",(can==0)?'N':'Y');
}
scanf("%s",o);
}
return 0;
}
Supplementary Notes on the Final Appearance
This very troublesome problem must be clearly thought out and then written, otherwise it will take a lot of time to debug.
So I used to write code so silly...
I thought it was only recently that I caught the trouble of always writing inscriptions.==