zoukankan      html  css  js  c++  java
  • Help with Intervals 线段树区间更新

      题意:给你一个初始为空的集合,对其进行5种操作若干遍,输出最终的集合。

     

      设S为一开始的集合,则: U  T 表示 S=S∪T

                I   T 表示 S=S∩T

                  D  T 表示 S=S-T

                  C  T 表示 S=T-S

                  S  T 表示 S=S异或T

     

      思路:用线段树模拟区间操作,叶子结点为1代表区间存在,0代表不存在,因为区间有开区间和闭区间两种,单单用叶子结点模拟自然数实现不了开区间,所以我们对坐标系×2扩大,原来的闭区间整数点对应扩大后的偶数点,1 2 3 4 5 变成2 4 6 8 10,原来的开区间例如(2,3】,扩大后变成(4,6】,再将开区间的端点相中心靠拢(4,6】->【5,6】由于新坐标系的偶数对应原坐标系,则新坐标系的奇数就可以用来实现开区间,然后区间更新实现操作即可。

      具体做法:设区间T为【L,R】,U T就是将T区间全更新为1。I T就是将【0,L-1】和【R+1,maxn】更新为0,因为求交集,则T区间以外的区间就不能存在,T区间之内的任由原来的S怎么地,就实现了交集。D T 就是将区间T变为0。对于C T,则是将T区间翻转,将T区间外变成0,因为是T-S,则T区间外一定是0,T区间内,S内就变为0,外就是1,就是翻转嘛。对于异或,S有的T没有的,T有的S没有的,这样的目标区间只需要将T区间翻转即可,T区间外的自然不影响,则S有的T没有的得到了保留,对于T区间内,有S的地方变为了0,没S的地方变成了1,所以即可达到操作!

    AC代码:

    #include<iostream>
    #include<stdio.h>
    #include<string.h>
    using namespace std;
    const int maxn=2e5+10;
    int col[maxn<<2];
    
    void pushdown(int rt){
        if(col[rt]==2){
            col[rt<<1]=1-col[rt<<1];
            col[rt<<1|1]=1-col[rt<<1|1];
            col[rt]=-1;
        }
        if(col[rt]!=-1){
            col[rt<<1]=col[rt<<1|1]=col[rt];
            col[rt]=-1;
        }
    }
    void check(){
        cout<<"**********************
    ";
        for(int i=1;i<=50;i++)
            cout<<col[i]<<" ";
        cout<<"
    ********************
    ";
    }
    
    void updata(int L,int R,int val,int l,int r,int rt){
        if(L<=l&&r<=R){
            if(val==2) col[rt]=1-col[rt];
            else col[rt]=val;
            return;
        }
        pushdown(rt);
        int m=l+r>>1;
        if(L<=m)
            updata(L,R,val,l,m,rt<<1);
        if(R>m)
            updata(L,R,val,m+1,r,rt<<1|1);
    }
    
    int search(int pos,int l,int r,int rt){
        if(l==r){
            return col[rt];
        }
        int m=l+r>>1;
        pushdown(rt);
        if(pos<=m)
            return search(pos,l,m,rt<<1);
        else
            return search(pos,m+1,r,rt<<1|1);
    }
    
    
    
    int main()
    {
         int a,b;
        char s,sl,sr,sm;
        memset(col,0,sizeof(col));
        while(~scanf(" %c %c%d %c%d %c",&s,&sl,&a,&sm,&b,&sr)){
            a<<=1;
            b<<=1;
            if(sl=='(') a++;
            if(sr==')') b--;
            if(s=='U') updata(a,b,1,0,maxn,1);
            if(s=='I'){
                   if(a>0)
                    updata(0,a-1,0,0,maxn,1);
                updata(b+1,maxn,0,0,maxn,1);
            }
            if(s=='D')  updata(a,b,0,0,maxn,1);
            if(s=='C'){
                updata(a,b,2,0,maxn,1);
                if(a>0)
                    updata(0,a-1,0,0,maxn,1);
                updata(b+1,maxn,0,0,maxn,1);
            }
            if(s=='S'){
                updata(a,b,2,0,maxn,1);
              }
        }
        int flag=0,k=0;
        for(int i=0;i<maxn;i++){
            int now=search(i,0,maxn,1);
            if(k==0&&now==1){
                if(i%2==0)
                    printf("[%d,",i/2);
                else
                    printf("(%d,",i/2);
                k=1;
                flag=1;
            }
            if(k==1&&now==0){
                int index=i-1;//最后一个1的下标
                if(index%2==0)
                    printf("%d] ",(index+1)/2);
                else
                    printf("%d) ",(index+1)/2);//如果是奇数,则表示的是index+1这个右端点的开区间
                    //若index=5 则原区间是...,3)
                k=0;
            }
        }
        if(flag==0) printf("empty set
    ");
        return 0;
    }
    /*
    U [1,5]
    D [3,3]
    S [2,4]
    C (1,5)
    I (2,3]
    */
  • 相关阅读:
    UVA 12338
    最短路问题
    菜鸟调错(十)——启动Tomcat报错“Unsupported major.minor version xxx ”
    Servlet总结(一)
    <html>
    Android Developer:Allocation Tracker演示
    H2数据库集群
    安卓通过广播自己主动回填短信验证码
    江湖问题研究-- intent传递有没有限制大小,是多少?
    spring 配置文件被加载两次
  • 原文地址:https://www.cnblogs.com/qq2210446939/p/12182096.html
Copyright © 2011-2022 走看看