P5568 [SDOI2008]校门外的区间(线段树)

线段树维护区间取反和区间覆盖操作。

注意他们的优先级。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pll;
typedef pair<int,pll> plll;
const int N=1e6+10;
struct node{
    int l,r;
    int rev;
    int cnt;
    int lazy;
}tr[N];
int ans[N];
void build(int u,int l,int r){
    if(l==r){
        tr[u]={l,r,0,0,-1};
    }
    else{
        tr[u]={l,r,0,0,-1};
        int mid=l+r>>1;
        build(u<<1,l,mid);
        build(u<<1|1,mid+1,r);
    }
}
void pushdown(int u){
    if(tr[u].lazy!=-1){
        int x=tr[u].lazy;
        tr[u<<1].lazy=x;
        tr[u<<1|1].lazy=x;
        tr[u<<1].rev=0;
        tr[u<<1|1].rev=0;
        tr[u].lazy=-1;
    }
    if(tr[u].rev){
        tr[u<<1].rev^=1;
        tr[u<<1|1].rev^=1;
        tr[u].rev=0;
    }
}
void modify(int u,int l,int r,int x){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].lazy=x;
        tr[u].rev=0;
        return ;
    }
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        modify(u<<1,l,r,x);
    if(r>mid)
        modify(u<<1|1,l,r,x);
}
void change(int u,int l,int r){
    if(tr[u].l>=l&&tr[u].r<=r){
        tr[u].rev^=1;
        return ;
    }
    pushdown(u);
    int mid=tr[u].l+tr[u].r>>1;
    if(l<=mid)
        change(u<<1,l,r);
    if(r>mid)
        change(u<<1|1,l,r);
}
void query(int u,int l,int r){
    if(l==r){
        if(tr[u].lazy==-1){
            if(tr[u].rev==0)
                ans[l]=0;
            else
                ans[l]=1;
        }
        else{
            ans[l]=tr[u].lazy^tr[u].rev;
        }
        return ;
    }
    pushdown(u);
    int mid=l+r>>1;
    query(u<<1,l,mid);
    query(u<<1|1,mid+1,r);
}
int main(){
    //ios::sync_with_stdio(false);
    int m;
    string s;
    build(1,0,150000);
    int n=150000;
    while(getline(cin,s)){
        int L=0,R=0,i=3;
        while(s[i]>='0'&&s[i]<='9') L=L*10+s[i++]-'0';
        L<<=1;
        L+=(s[2]=='(');
        i++;
        while(s[i]>='0'&&s[i]<='9') R=R*10+s[i++]-'0';
        R<<=1;
        R-=(s[i]==')');//读入数据需要一点点改变,注意细节
        if(s[0]=='U') modify(1,L,R,1);else
        if(s[0]=='I'){
            if(0<=L-1) modify(1,0,L-1,0);
            if(R+1<=n) modify(1,R+1,n,0);
        }else
        if(s[0]=='D') modify(1,L,R,0);else
        if(s[0]=='C'){
            if(0<=L-1)  modify(1,0,L-1,0);
            if(R+1<=n) modify(1,R+1,n,0);
            change(1,L,R);
        }else
        if(s[0]=='S') change(1,L,R);
    }
    query(1,0,n);
    int cnt=0;
    int i;
    int L=0,R=0;
    for(int i=0;i<=n;i++){
        if(ans[i]&&(i==0||!ans[i-1])) L=i;
        if(ans[i]&&(i==n||!ans[i+1])){
            R=i;
            cnt++;
            if(L&1) printf("(%d,",L/2);
            else printf("[%d,",L/2);
            if(R&1) printf("%d) ",R/2+1);
            else printf("%d] ",R/2);
        }
    }
    if(!cnt)
        cout<<"empty set"<<endl;
    return 0;
}
View Code

 

posted @ 2020-08-23 09:52  朝暮不思  阅读(136)  评论(0编辑  收藏  举报