[SHOI2008]堵塞的交通traffic
来源:互联网 发布:淘宝客户端怎么改差评 编辑:程序博客网 时间:2024/06/11 02:01
Description
有一天,由于某种穿越现象作用,你来到了传说中的小人国。小人国的布局非常奇特,整个国家的交通系统可以被看成是一个
Close
Open
Ask
Input
第一行只有一个整数
Output
对于每个查询,输出一个“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
HINT
题解:JudgeOnline/upload/201604/sol(4).rar
Source
思路
首先对于一个只有一行的情况,可以很容易的用线段树维护。
但是对于两行的情况,就需要用一些奇怪的技巧了。
考虑下面这个图:
从
那么可以维护
具体一点,假设有区间为:
q ———r
z ———v
那么需要维护
那么更新时就通过这个更新,还有区间
询问就按照上面的查询方法写。
代码
其实是可以不用写这么多的,只是我写的太长了……
#include <cstdio>#include <algorithm>const int maxn=100000;struct data{ int we,xc,qr,zv,qz,rv,qv,rz; //解释一下变量名的含义: //将键盘上左手边的一块看成一个矩形 //就是 //qwer //asdf //zxcv //把q,r,z,v看成矩形的4个顶点 //w和x看成是中间点 //e和c看成是中间点的编号+1位置的点 //连起来写的两个字符表示两个位置的联通性};struct segment_tree{ data val[(maxn<<2)+10]; inline int merge(data &d,data l,data r) //精华部分,自己画个图就明白了 //意思是将l和r区间合并成一个区间d { d.qz=l.qz|(l.qr&d.we&r.qz&d.xc&l.zv); d.rv=r.rv|(r.qr&d.we&l.rv&d.xc&r.zv); d.qr=(l.qv&d.xc&r.rz)|(l.qr&d.we&r.qr); d.zv=(l.zv&d.xc&r.zv)|(l.rz&d.we&r.qv); d.qv=(l.qv&d.xc&r.zv)|(l.qr&d.we&r.qv); d.rz=(l.zv&d.xc&r.rz)|(l.rz&d.we&r.qr); return 0; } int build(int now,int left,int right) //建树 { if(left==right) { val[now].qr=val[now].zv=val[now].we=val[now].xc=1; val[now].qz=val[now].rv=val[now].qv=val[now].rz=0; return 0; } int mid=(left+right)>>1; val[now].we=val[now].xc=0; build(now<<1,left,mid); build(now<<1|1,mid+1,right); merge(val[now],val[now<<1],val[now<<1|1]); return 0; } int rchange(int now,int left,int right,int pos,int cval) //将(1,pos)这个点与(2,pos)这个点的联通性变成cval { if(left==right)//说明当前这个位置就是pos,直接修改 { val[now].qz=val[now].rv=val[now].qv=val[now].rz=cval; return 0; } int mid=(left+right)>>1; if(pos<=mid)//寻找pos { rchange(now<<1,left,mid,pos,cval); } else { rchange(now<<1|1,mid+1,right,pos,cval); } merge(val[now],val[now<<1],val[now<<1|1]);//更新这个点的val return 0; } int uchange(int now,int left,int right,int pos,int cval) //将(1,pos)这个点和(1,pos+1)这个点之间的联通性修改为cval { int mid=(left+right)>>1; if(mid==pos)//如果中点就是pos,直接修改w->e的值 { val[now].we=cval; merge(val[now],val[now<<1],val[now<<1|1]); return 0; } if(pos<=mid)//寻找pos { uchange(now<<1,left,mid,pos,cval); } else { uchange(now<<1|1,mid+1,right,pos,cval); } merge(val[now],val[now<<1],val[now<<1|1]); return 0; } int dchange(int now,int left,int right,int pos,int cval) //将(2,pos)这个点和(2,pos+1)这个点的联通性修改为cval { int mid=(left+right)>>1; if(mid==pos)//如果中点就是pos,那么将x->c的值修改 { val[now].xc=cval; merge(val[now],val[now<<1],val[now<<1|1]); return 0; } if(pos<=mid)//寻找pos { dchange(now<<1,left,mid,pos,cval); } else { dchange(now<<1|1,mid+1,right,pos,cval); } merge(val[now],val[now<<1],val[now<<1|1]);//更新这个点的val return 0; } data query(int now,int left,int right,int s,int t) //询问s到t区间的联通性(用一个data表示) { if((s<=left)&&(right<=t)) { return val[now]; //如果已经被完全包含,直接返回这个点的val } int mid=(left+right)>>1; if(s>mid) { return query(now<<1|1,mid+1,right,s,t); //如果完全包含于右区间,返回右区间的寻找结果 } else if(t<=mid) { return query(now<<1,left,mid,s,t); //如果完全含于左区间,返回左区间的寻找结果 } else { data res=val[now]; merge(res,query(now<<1,left,mid,s,t),query(now<<1|1,mid+1,right,s,t)); //两个区间一定是连起来的,直接用val[now]的信息合并左边和右边 return res; } }};segment_tree st;int n;char ch[10];inline int read(){ int x=0,f=1; char ch=getchar(); while((ch<'0')||(ch>'9')) { if(ch=='-') { f=-f; } ch=getchar(); } while((ch>='0')&&(ch<='9')) { x=x*10+ch-'0'; ch=getchar(); } return x*f;}int main(){ n=read(); st.build(1,1,n);//首先建树 while(scanf("%s",ch)!=EOF) { if(ch[0]=='E') { break; } int ax=read(),ay=read(),bx=read(),by=read(); if(ay>by)//保证a一定在b右侧 { std::swap(ax,bx); std::swap(ay,by); } if(ch[0]=='O') { //分情况讨论Open的道路 if(ay==by) { st.rchange(1,1,n,ay,1); } else if(ax==1) { st.uchange(1,1,n,ay,1); } else { st.dchange(1,1,n,ay,1); } } else if(ch[0]=='C') { //分情况讨论Close的道路 if(ay==by) { st.rchange(1,1,n,ay,0); } else if(ax==1) { st.uchange(1,1,n,ay,0); } else { st.dchange(1,1,n,ay,0); } } else { data res=st.query(1,1,n,ay,by),l=st.query(1,1,n,1,ay),r=st.query(1,1,n,by,n); //res是[ay,by]的联通性,l是[1,ay]的联通性,r是[by,n]的联通性 int ans; //下面是分情况讨论a和b的横坐标,计算过程就是上面的 if((ax==1)&&(bx==1)) { ans=res.qr|(l.rv&res.rz)|(r.qz&res.qv)|(l.rv&r.qz&res.zv); } else if((ax==1)&&(bx==2)) { ans=res.qv|(l.rv&res.zv)|(r.qz&res.qr)|(l.rv&r.qz&res.rz); } else if((ax==2)&&(bx==1)) { ans=res.rz|(l.rv&res.qr)|(r.qz&res.zv)|(l.rv&r.qz&res.qv); } else { ans=res.zv|(l.rv&res.qv)|(r.qz&res.rz)|(l.rv&r.qz&res.qr); } if(ans) { puts("Y"); } else { puts("N"); } } } return 0;}
- [SHOI2008]堵塞的交通traffic
- [SHOI2008]堵塞的交通traffic
- BZOJ 1018: [SHOI2008]堵塞的交通traffic
- 【BZOJ 1018】 [SHOI2008]堵塞的交通traffic
- 【bzoj1018】【SHOI2008】【堵塞的交通traffic】
- BZOJ1018 [SHOI2008]堵塞的交通traffic
- 1018: [SHOI2008]堵塞的交通traffic
- 【BZOJ 1018】 [SHOI2008]堵塞的交通traffic
- bzoj1018[SHOI2008]堵塞的交通traffic
- BZOJ 1018 SHOI2008 堵塞的交通traffic
- BZOJ1018: [SHOI2008]堵塞的交通traffic
- bzoj1018 [SHOI2008]堵塞的交通traffic
- bzoj1018 [SHOI2008]堵塞的交通traffic
- 1018: [SHOI2008]堵塞的交通traffic
- [bzoj1018]:[SHOI2008]堵塞的交通traffic
- bzoj1018: [SHOI2008]堵塞的交通traffic 线段树区间合并
- 【BZOJ】【P1018】【SHOI2008】【堵塞的交通traffic】【题解】【线段树】
- BZOJ 1018 SHOI2008 堵塞的交通traffic 线段树
- 2.第一个Java程序Hello Java!
- python读取caffemodel
- Master代码改动后怎么pull到自己的分支
- 一个滑动特效
- Web响应式布局设计简介
- [SHOI2008]堵塞的交通traffic
- 【博文视点送书福利】Java程序员也应该会点产品经理的活!另外还要有小程序哦!
- jquery mouse事件小坑
- hdu1065 Wooden Sticks
- HDOJ 1029 Ignatius and the Princess IV
- Ubuntu上 linux-image-extra-4.13.0-17-generic ,linux-image-generic,linux-generic错误解决方法
- 宝塔Linux面板5.X正式版安装\SSL配置\异地备份教程
- 60使用nanopim1plus查看HDMI显示分辨率的问题(分色排版)V1.0
- Centos 系统swap虚拟内存添加与删除配置