您的位置:首页 > 其它

[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几次就好了

代码:

#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");
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: