[BZOJ3226][SDOI2008]校门外的区间(线段树)
2018-03-07 21:02
281 查看
fBAgGjwvfrKU
然而一开始愚蠢的up选择1-base为区间,base+1-Max为端点,然后就开始无穷无尽的调试,最后还没法输出
没办法了,那就让端点和区间挨着吧,一个端点一个区间。。。
这些操作也很明了了
And 两侧变成0
Or 区间全1
已有-新读 区间全0
新读-已有 两侧全0,区间内取反
异或 区间内取反
还有一个问题,先处理delta还是先all呢?我们发现当delta在下面的时候,不管下面打不打完标记,只要上面有一个all就跟delta没啥关系了,当all在下面的时候,我们必须先处理完下面的然后再让delta取反。由此观之,我们要先处理all。其次多pushdown几次就好了
题目:
我是超链接题解:
如何处理开闭区间?开两倍的节点,一部分代表端点,一部分代表区间然而一开始愚蠢的up选择1-base为区间,base+1-Max为端点,然后就开始无穷无尽的调试,最后还没法输出
没办法了,那就让端点和区间挨着吧,一个端点一个区间。。。
这些操作也很明了了
And 两侧变成0
Or 区间全1
已有-新读 区间全0
新读-已有 两侧全0,区间内取反
异或 区间内取反
还有一个问题,先处理delta还是先all呢?我们发现当delta在下面的时候,不管下面打不打完标记,只要上面有一个all就跟delta没啥关系了,当all在下面的时候,我们必须先处理完下面的然后再让delta取反。由此观之,我们要先处理all。其次多pushdown几次就好了
代码:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int Max=65536*2+1; int delta[Max*4],w[Max*4],all[Max*4]; void pushdown(int now,int l,int r) { if(l==r) { if(all[now]!=-1) w[now]=all[now]; w[now]^=delta[now]; all[now]=-1;delta[now]=0; return; } if(all[now]!=-1) { all[now<<1]=all[now<<1|1]=all[now]; delta[now<<1]=delta[now<<1|1]=0; ///// } delta[now<<1]^=delta[now];delta[now<<1|1]^=delta[now]; all[now]=-1;delta[now]=0; } void change(int now,int l,int r,int lrange,int rrange,int v) { if (lrange>rrange) return; pushdown(now,l,r); if (lrange<=l && rrange>=r) {all[now]=v;return;} int mid=(l+r)>>1;pushdown(now,l,r); if (lrange<=mid) change(now<<1,l,mid,lrange,rrange,v); if (rrange>mid) change(now<<1|1,mid+1,r,lrange,rrange,v); pushdown(now,l,r); } void qufan(int now,int l,int r,int lrange,int rrange) { if (lrange>rrange) return; pushdown(now,l,r); if (lrange<=l && rrange>=r) {delta[now]^=1; return;} int mid=(l+r)>>1;pushdown(now,l,r); if (lrange<=mid) qufan(now<<1,l,mid,lrange,rrange); if (rrange>mid) qufan(now<<1|1,mid+1,r,lrange,rrange); pushdown(now,l,r); } int qurry(int now,int l,int r,int x) { pushdown(now,l,r); if (l==r) return w[now]; int mid=(l+r)>>1; if (x<=mid) return qurry(now<<1,l,mid,x); else return qurry(now<<1|1,mid+1,r,x); } int main() { char st[5],s[15]; memset(all,-1,sizeof(all)); while (scanf("%s",st)!=EOF) { scanf("%s",s+1); int len=strlen(s+1),l,r,x=0,z=0,y=0; for (int j=1;j<=len;j++) { if (j==1) {if (s[j]=='(') z=1; continue;} if (j==len) {if (s[j]==')') y=-1; continue;} if (s[j]==',') {l=x;x=0;continue;} x=x*10+s[j]-'0'; } r=x; l=l*2+1+z;//0 r=r*2+1+y;//0 switch (st[0]) { case 'U':change(1,1,Max,l,r,1);break; case 'I':change(1,1,Max,1,l-1,0);change(1,1,Max,r+1,Max,0);break; case 'D':change(1,1,Max,l,r,0);break; case 'C':change(1,1,Max,1,l-1,0);change(1,1,Max,r+1,Max,0);qufan(1,1,Max,l,r);break; case 'S':qufan(1,1,Max,l,r);break; } } int be=0,la=0;bool fff=0,yx=0; for (int i=1;i<=Max;i++) { if (qurry(1,1,Max,i)) { if (yx==0) be=i,yx=1; fff=1; la=i; } else if (yx) { if (be%2) printf("[");else printf("("); printf("%d,%d",(be-1)/2,la/2); if (la%2) printf("] ");else printf(") "); yx=0; } } if (!fff) printf("empty set"); }
相关文章推荐
- [bzoj3226][Sdoi2008]校门外的区间——线段树
- BZOJ 题目 3226: [Sdoi2008]校门外的区间(线段树区间交并差异或)
- [BZOJ]3226: [Sdoi2008]校门外的区间 线段树
- bzoj 3226 [Sdoi2008]校门外的区间(线段树)
- bzoj3226: [Sdoi2008]校门外的区间 线段树
- [线段树 标记] BZOJ 3226 [Sdoi2008]校门外的区间
- bzoj 3226: [Sdoi2008]校门外的区间(线段树)
- 【BZOJ】【P3226】【Sdoi2008】【校门外的区间】【题解】【线段树】
- BZOJ 3226: [Sdoi2008]校门外的区间
- 【bzoj3226】[Sdoi2008]校门外的区间
- 【SDOI2008】【BZOJ3226】校门外的区间
- 【分块】bzoj3226 [Sdoi2008]校门外的区间
- BZOJ-3226 [SDOI2008]校门外的区间
- bzoj 3226: [Sdoi2008]校门外的区间
- BZOJ 3226 [SDOI2008]校门外的区间
- 3226: [Sdoi2008]校门外的区间 线段树
- 3226: [Sdoi2008]校门外的区间
- 3226: [Sdoi2008]校门外的区间
- 「BZOJ3226」[SDOI2008] 校门外的区间(线段树好题)
- 【BZOJ3226】【codevs2297】校门外的区间,线段树