您的位置:首页 > 其它

【分块】bzoj3226 [Sdoi2008]校门外的区间

2014-11-27 12:15 387 查看
题解见 : http://blog.csdn.net/iamzky/article/details/41088151
ORZ ZKY

2个懒标记:是否翻转,覆盖成了什么。

怎么处理一个块上有两个标记的情况呢?

若该块原来没有任何标记,或要打的标记和原本的标记种类相同,则直接打上标记;

若已有翻转标记,再覆盖时则先清除翻转标记,再打上覆盖标记;

若已有覆盖标记,再翻转时,则直接将覆盖标记取反。

So 某个块上同时只会有1个标记。

P.S.分块此题挺快的……

#include<cstdio>
#include<cstring>
using namespace std;
#define sz 370
const int n=131070;
char op[1],cl,cr;
int x,y,num[132000],l[sz],r[sz],cov[sz],sum;
bool a[132000],spin[sz],goal;
void makeblock()
{
for(sum=1;sum*sz<n;++sum)
{
l[sum]=r[sum-1]+1; r[sum]=sum*sz;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
}
l[sum]=r[sum-1]+1; r[sum]=n;
for(int i=l[sum];i<=r[sum];++i) num[i]=sum;
memset(cov,-1,sizeof(cov));
}
void pushdown(const int &p)
{
if(cov[p]!=-1)
{
for(int i=l[p];i<=r[p];i++) a[i]=cov[p];
cov[p]=-1;
}
else if(spin[p])
{
for(int i=l[p];i<=r[p];i++) a[i]^=1;
spin[p]=0;
}
}
void update(const int &L,const int &R,const bool &sym)
{
pushdown(num[L]); pushdown(num[R]);
if(num[L]==num[R]) {for(int i=L;i<=R;++i) a[i]=sym;}
else
{
for(int i=L;i<=r[num[L]];++i) a[i]=sym;
for(int i=l[num[R]];i<=R;++i) a[i]=sym;
for(int i=num[L]+1;i<num[R];++i) {spin[i]=0; cov[i]=sym;}
}
}
void rotate(const int &L,const int &R)
{
pushdown(num[L]); pushdown(num[R]);
if(num[L]==num[R]) {for(int i=L;i<=R;++i) a[i]^=1;}
else
{
for(int i=L;i<=r[num[L]];++i) a[i]^=1;
for(int i=l[num[R]];i<=R;++i) a[i]^=1;
for(int i=num[L]+1;i<num[R];++i)
if(cov[i]==-1) spin[i]^=1;
else cov[i]^=1;
}
}
int Ma(const int &v,const char &c)
{
if(c=='['||c==']') return (v<<1);
else if(c=='(') return (v<<1)+1;
else return (v<<1)-1;
}
int main()
{
makeblock();
while(scanf("%s %c%d,%d%c",op,&cl,&x,&y,&cr)!=EOF)
{
if(op[0]=='U') update(Ma(x,cl),Ma(y,cr),1);
else if(op[0]=='I')
{
if(x) update(0,Ma(x,cl)-1,0);
if(y!=65535) update(Ma(y,cr)+1,65535<<1,0);
}
else if(op[0]=='D') update(Ma(x,cl),Ma(y,cr),0);
else if(op[0]=='C')
{
rotate(Ma(x,cl),Ma(y,cr));
if(x) update(0,Ma(x,cl)-1,0);
if(y!=65535) update(Ma(y,cr)+1,65535<<1,0);
}
else rotate(Ma(x,cl),Ma(y,cr));
}
int head=0;
for(int i=1;i<=sum;++i) pushdown(i);
for(int i=0;i<=n;++i)
{
if(((!i) && a[i]) || (a[i] && (!a[i-1]))) head=i;
if((i==n && a[i]) || (a[i] && (!a[i+1])))
{
goal=1;
if(head&1) putchar('(');
else putchar('[');
printf("%d,",head>>1);
if(i&1) {printf("%d",i+1>>1); putchar(')');}
else {printf("%d",i>>1); putchar(']');}
putchar(' ');
}
}
if(!goal) puts("empty set");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: