[线段树 标记] BZOJ 3226 [Sdoi2008]校门外的区间

放标记,两个标记搞死...

还因为没判 l>r 狂T

哪怕复习线段树这种称得上简单的数据结构 也能体会到很多东西 

#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;

inline int read()
{
    int x=0,f=0;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='(')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	if(ch==')')f=1;
    return x*2-f;
}

struct Seg{
	int M,TH;
	int H[600005],R[600005];
	inline void Build(int n){
		for (M=1;M<n+2;M<<=1,TH++);
		for (int i=1;i<M;i++)
			H[i]=-1;
	}
	inline void pushdown(int x){
		if (R[x])
		{
			R[x<<1]^=1; if (H[x<<1]!=-1) H[x<<1]^=1;
			R[x<<1|1]^=1; if (H[x<<1|1]!=-1) H[x<<1|1]^=1;
			R[x]^=1;
		}
		if (H[x]!=-1)
		{
			H[x<<1]=H[x<<1|1]=H[x];
			H[x]=-1;
		}
	}
	inline void Pushdown(int rt){
		int p;
		for (int i=TH;i;i--)
			pushdown(rt>>i);
	}
	inline void Reverse(int s,int t){
		if (s>t) return;
		for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;s>>=1,t>>=1)
		{
			if (~s&1) { R[s^1]^=1; if (H[s^1]!=-1) H[s^1]^=1; }
			if ( t&1) { R[t^1]^=1; if (H[t^1]!=-1) H[t^1]^=1; }
		}
	}
	inline void Change(int s,int t,int c){
		if (s>t) return;
		for (Pushdown(s+=M-1),Pushdown(t+=M+1);s^t^1;s>>=1,t>>=1)
		{
			if (~s&1) H[s^1]=c,R[s^1]=0;
			if ( t&1) H[t^1]=c,R[t^1]=0;
		}
	}
	inline int Query(int s){
		Pushdown(s+=M);
		return H[s];
	}
}SEG;

const int n=(65536*2+1);
//const int n=(5*2+1);

int main()
{
	int a,b;
	char ch[3];
	char type, flag_l, flag_r,flag=0;
	freopen("t.in","r",stdin);
	freopen("t.out","w",stdout);
	SEG.Build(n);
	while (~scanf("%s",ch))
    {
	    a=read(); b=read();
        a+=2; b+=2;
		switch(ch[0])
		{
			case 'U':
				SEG.Change(a,b,1);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				break;
			case 'I':
				SEG.Change(1,a-1,0);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				SEG.Change(b+1,n,0);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				break;
			case 'D':
				SEG.Change(a,b,0);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				break;
			case 'C':
				SEG.Change(1,a-1,0);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				SEG.Change(b+1,n,0);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				SEG.Reverse(a,b);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				break;
			case 'S':
				SEG.Reverse(a,b);
//				for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
				break;
		}
	}
	int start=-1,last=-1;
	flag=0;
//	for(int i=1;i<=n;i++) printf("%d ",SEG.Query(i)); printf("\n");
	for(int i=1;i<=n;i++)
		if(SEG.Query(i))
		{
			if(start==-1) start=i;
			last=i;
		}
		else 
		{
			if(start!=-1)
			{
				if(flag)printf(" ");
				else flag=1;
				if(start&1)printf("(");
				else printf("[");
				printf("%d",start/2-1);
				printf(",");
				printf("%d",(last+1)/2-1);
				if(last&1)printf(")");
				else printf("]");
			}
			last=start=-1;
		}
	if(!flag) 
		printf("empty set\n");
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值