1 条题解

  • 0
    @ 2025-10-8 17:08:10
    /*
    用线段树维护当前区间且维护两个标记cov,tag,分别代表覆盖和翻转的标记
    五种运算如下:
    U T:S=S ∪T,T区间覆盖1
    I T:S=S ∩T,T区间范围内覆盖0
    D T:S=S - T,T区间覆盖0
    C T:S=T - S,全集范围内01翻转,转到I操作
    S T:S=S ⊕T,T区间范围内01翻转
    
    细节处理: 
    输入输出细节
    开闭用*2方法处理
    覆盖和翻转的优先级
    */
    #include <bits/stdc++.h>
    #define lc (p<<1)
    #define rc ((p<<1)|1)
    #define mid ((tr[p].l+tr[p].r)>>1)
    using namespace std;
    const int N=1.4e5;
    struct node{int l,r,cov,tag;}tr[N<<2];int ans[N];
    void bt(int p, int l, int r)
    {
    	tr[p]=node{l,r,-1,0};
    	if(l==r)return;
    	bt(lc,l,mid),bt(rc,mid+1,r);
    }
    void pushdown(int p)
    {
    	if(tr[p].cov!=-1)
    	{
    		tr[lc].cov=tr[rc].cov=tr[p].cov;
    		tr[lc].tag=tr[rc].tag=0;tr[p].cov=-1;
    	}
    	if(tr[p].tag)
    	{
    		tr[lc].tag^=1,tr[rc].tag^=1;tr[p].tag=0;
    	}
    }
    void change(int p, int l, int r, int k)
    {
    	if(tr[p].l>r || tr[p].r<l || l>r) return;
    	if(l<=tr[p].l && tr[p].r<=r)
    	{
    		if(k!=2)tr[p].cov=k,tr[p].tag=0;else tr[p].tag^=1;
    		return;
    	}
    	pushdown(p);
    	change(lc,l,r,k),change(rc,l,r,k);
    }
    
    void query(int p)
    {
    	if(tr[p].l==tr[p].r)
    	{
    		ans[tr[p].l]=tr[p].cov==-1 ? 0 : tr[p].cov^tr[p].tag;
    		return;
    	}
    	pushdown(p);
    	query(lc), query(rc);
    }
    void print()
    {
    	query(1);
    	int flag=0,Empty=0;
    	for(int i=0;i<=N;++i){
    		if(ans[i] && !flag){
    			flag = Empty = 1;
    			if (i & 1) printf("(%d,", (i - 1) >> 1); else printf("[%d,", i >> 1);
    		}
    		if(!ans[i] && flag){
    			flag = 0;
    			if (i & 1) printf("%d] ", (i - 1) >> 1); else printf("%d) ", i >> 1);
    		}
    	}
    	if (!Empty) puts("empty set");
    }
    
    int main()
    {
    	bt(1,0,N);
    	char s[20],ss[110],c1,c2;int l,r;
    	while(scanf("%s",s)!=EOF)
    	{
    		scanf("%s",ss);
    		sscanf(ss,"%c%d,%d%c",&c1,&l,&r,&c2);l<<=1;r<<=1;
    		if(c1=='(')l++;
    		if(c2==')')r--;
    		if(s[0]=='U')change(1,l,r,1);
    		else if(s[0]=='I')change(1,0,l-1,0), change(1,r+1,N,0); 
    		else if(s[0]=='D')change(1,l,r,0); 
    		else if(s[0]=='C')change(1,0,N,2),change(1,0,l-1,0),change(1,r+1,N,0);
    		else change(1,l,r,2);
    	}
    	print();
    	return 0;
    }
    
    • 1

    *【线段树】模拟集合操作[SDOI2008] 校门外的区间

    信息

    ID
    4891
    时间
    1000ms
    内存
    128MiB
    难度
    8
    标签
    递交数
    11
    已通过
    7
    上传者