zoukankan      html  css  js  c++  java
  • 线段树专辑 —— pku 3225 Help with Intervals

    http://poj.org/problem?id=3225

    这题很有意思,对于[0,65535]这么一个区间,初始值为0,问最后为连续1的子区间有哪些。

    很有趣的是,这题涉及到了开区间和闭区间,即() 和 [] 。确是比较棘手!

    解决的办法是将所给的数据范围乘以2,然后根据给的是开区间或则是闭区间修改数据,例如:给你(2,3]这样的数据,如何处理呢?

    我们将范围乘以2,得到(4,6],然后,如果左边是开区间,则将4加1,得到5,同理,如果右边是开区间,则将6减去一个1。

    为什么这样做呢? 看看,因为数据乘以2后,得到的结果一定是偶数,而偶数加一减一后,肯定得到奇数。也就是说,如果最后得到的数据是偶数,那就是闭区间,如果得到的数据是奇数,那就对应着开区间。

    再来分析一下5个基本操作:

    U操作最简单了,只需要将T的区间范围在线段树中跟新为1即可

    D操作一样简单,只需要将T的区间范围在线段树中跟新为0即可

    S操作:将T区间范围在线段树中取反(1->0,0->1)为什么这样做呢?着不是异或吗,怎么变成取反了?仔细分析一下便知道,因为T的数据全是1,1^1=0,1^0=1,这不就是取反吗?!

    I操作:假设T区间为[a,b],那么将区间[0,a-1]和区间[b+1,max]跟新为0即可,为什么呢?因为T全是1,s集合和T取交的话还是等于s。

    C操作:假设T区间为[a,b],那么先将将区间[0,a-1]和区间[b+1,max]跟新为0,再对区间[a,b]取反,为什么?最后一个了,自己想想呗~

    View Code
      1 #include<iostream>
    2 #include<string>
    3 #include<cmath>
    4 #include<algorithm>
    5 using namespace std;
    6
    7 #define inf 65535
    8
    9 struct node
    10 {
    11 int l;
    12 int r;
    13 int cover; //记录线段是单色还是混色
    14 int change; //是否需要取反
    15 void changeedit()
    16 {
    17 if(cover!=-1) //如需要取反,而线段又是单色,则直接取反
    18 cover^=1;
    19 else
    20 change^=1; //否则在原先需要取反的基础上再取反
    21 }
    22 };
    23
    24 node tree[1000000];
    25
    26 void build(int i,int l,int r)
    27 {
    28 tree[i].l=l;
    29 tree[i].r=r;
    30 tree[i].cover=0;
    31 tree[i].change=0;
    32 if(l==r)
    33 return;
    34 int mid=(l+r)/2;
    35 build(2*i,l,mid);
    36 build(2*i+1,mid+1,r);
    37 }
    38
    39 void updata(int i,int l,int r,int w) //直接更新覆盖
    40 {
    41 if(tree[i].l>r || tree[i].r<l)
    42 return;
    43 if(tree[i].l>=l && tree[i].r<=r)
    44 {
    45 tree[i].cover=w;
    46 tree[i].change=0;
    47 return;
    48 }
    49 if(tree[i].cover!=-1) //混色,向下传递
    50 {
    51 tree[2*i].cover=tree[2*i+1].cover=tree[i].cover;
    52 tree[2*i].change=tree[2*i+1].change=tree[i].change;
    53 tree[i].cover=-1;
    54 tree[i].change=0;
    55 }
    56 if(tree[i].change) //需要取反,则其子区间便取反
    57 {
    58 tree[2*i].changeedit();
    59 tree[2*i+1].changeedit();
    60 tree[i].change=0; //标记取消
    61 }
    62 updata(2*i,l,r,w);
    63 updata(2*i+1,l,r,w);
    64 if(tree[2*i].cover==tree[2*i+1].cover) //回溯标记颜色
    65 tree[i].cover=tree[2*i].cover;
    66 else
    67 tree[i].cover=-1;
    68 }
    69
    70 void updatas(int i,int l,int r) //取反
    71 {
    72 if(tree[i].l>r || tree[i].r<l)
    73 return;
    74 if(tree[i].l>=l && tree[i].r<=r)
    75 {
    76 if(tree[i].cover!=-1)
    77 tree[i].cover^=1;
    78 else
    79 tree[i].change^=1;
    80 return;
    81 }
    82 if(tree[i].cover!=-1)
    83 {
    84 tree[2*i].cover=tree[2*i+1].cover=tree[i].cover;
    85 tree[2*i].change=tree[2*i+1].change=tree[i].change;
    86 tree[i].cover=-1;
    87 tree[i].change=0;
    88 }
    89 if(tree[i].change)
    90 {
    91 tree[2*i].changeedit();
    92 tree[2*i+1].changeedit();
    93 tree[i].change=0;
    94 }
    95 updatas(2*i,l,r);
    96 updatas(2*i+1,l,r);
    97 if(tree[2*i].cover==tree[2*i+1].cover)
    98 tree[i].cover=tree[2*i].cover;
    99 else
    100 tree[i].cover=-1;
    101 }
    102
    103 int v[2*inf+2];
    104
    105 void find(int i,int l,int r)
    106 {
    107 if(tree[i].l>r || tree[i].r<l)
    108 return;
    109 if(tree[i].l==tree[i].r)
    110 {
    111 v[tree[i].l]=tree[i].cover;
    112 return;
    113 }
    114 if(tree[i].cover!=-1)
    115 {
    116 tree[2*i].cover=tree[2*i+1].cover=tree[i].cover;
    117 tree[2*i].change=tree[2*i+1].change=tree[i].change;
    118 tree[i].cover=-1;
    119 tree[i].change=0;
    120 }
    121 if(tree[i].change)
    122 {
    123 tree[2*i].changeedit();
    124 tree[2*i+1].changeedit();
    125 tree[i].change=0;
    126 }
    127 find(2*i,l,r);
    128 find(2*i+1,l,r);
    129 return ;
    130 }
    131
    132 int main()
    133 {
    134 //freopen("in.txt","r",stdin);
    135 char c,l,r;
    136 int a,b,max=0,i,j;
    137 build(1,0,2*inf);
    138 while(~scanf("%c %c%d,%d%c\n", &c, &l, &a, &b, &r))
    139 {
    140 a*=2; b*=2;
    141 if(l=='(')
    142 a++;
    143 if(r==')')
    144 b--;
    145 if(a>max)
    146 max=a;
    147 if(b>max)
    148 max=b;
    149 if(a>b)
    150 continue;
    151 if(c=='U')
    152 {
    153 updata(1,a,b,1);
    154 }
    155 else if(c=='D')
    156 {
    157 updata(1,a,b,0);
    158 }
    159 else if(c=='S')
    160 {
    161 updatas(1,a,b);
    162 }
    163 else if(c=='C')
    164 {
    165 updatas(1,a,b);
    166 updata(1,0,a-1,0);
    167 updata(1,b+1,max,0);
    168 }
    169 else
    170 {
    171 updata(1,0,a-1,0);
    172 updata(1,b+1,max,0);
    173 }
    174 }
    175 find(1,0,max);
    176 int flag=0;
    177 for(i=0;i<=max;i++) //查找有多少连续的1
    178 {
    179 if(v[i])
    180 {
    181 for(j=i+1;j<=max;j++)
    182 {
    183 if(!v[j])
    184 break;
    185 }
    186 b=j-1;
    187 if(flag)
    188 printf("");
    189 printf("%c%d,%d%c",i%2==1?'(':'[',i%2==1?(i-1)/2:i/2,b%2==1?(b+1)/2:b/2,b%2==1?')':']');
    190 flag=1;
    191 i=j;
    192 }
    193 }
    194 if(!flag)
    195 {
    196 printf("empty set");
    197 }
    198 cout<<endl;
    199 return 0;
    200 }



  • 相关阅读:
    【C/C++】【类和对象】计算类所占的字节数
    【算法】【单调栈】单调栈
    【算法】【字符串】C语言常用库函数实现
    【算法】【字符串】Leetcode哈希表相关高频面试题
    ubuntu20.04安装测试uhttpd
    华为Mate14上安装Ubuntu20.04纪要
    shell判断参数值是否在数组内的方法
    降低PDF质量
    Ubuntu 16.04上安装Global阅读源代码工具
    Linux下好用的屏幕录像软件kazam及截图软件shutter
  • 原文地址:https://www.cnblogs.com/ka200812/p/2247987.html
Copyright © 2011-2022 走看看