• HDU 3911 线段树区间合并、异或取反操作


    题目:http://acm.hdu.edu.cn/showproblem.php?pid=3911

     线段树区间合并的题目,解释一下代码中声明数组的作用:

    m1是区间内连续1的最长长度,m0是区间内连续0的最长长度,l1是从区间左端开始连续1的长度,r1是从区间右端开始连续1的长度,l0是从区间左端开始连续0的长度,r0是从区间右端开始连续0的长度,lazy标记该区间是否进行异或操作。

    之所以要同时保存1的连续长度和0的连续长度,是因为这道题设计取反操作,所以取反是,只需将对应的0、1长度调换一下就可以了

      1 #include<stdio.h>
      2 #include<algorithm>
      3 #define lson l,m,rt*2
      4 #define rson m+1,r,rt*2+1
      5 #define maxn 111111
      6 using namespace std;
      7 int m1[maxn*4],m0[maxn*4],l1[maxn*4],r1[maxn*4],l0[maxn*4],r0[maxn*4],lazy[maxn*4];
      8 void change(int rt){
      9     swap(m1[rt],m0[rt]);
     10     swap(l1[rt],l0[rt]);
     11     swap(r1[rt],r0[rt]);
     12 }
     13 void pushup(int l,int r,int rt){
     14     int m = (l+r)/2;
     15     //左边的长度等于左子区间左边的长度,右边的长度等于右子区间右边的长度,下同 
     16     l1[rt] = l1[rt*2];
     17     r1[rt] = r1[rt*2+1];
     18     
     19     l0[rt] = l0[rt*2];
     20     r0[rt] = r0[rt*2+1];
     21     //左边的长度等于区间左半长,则加上右子区间左边的长度,下同 
     22     if(l1[rt] == m-l+1)
     23         l1[rt] += l1[rt*2+1];
     24     if(r1[rt] == r-m)
     25         r1[rt] += r1[rt*2];
     26         
     27     if(l0[rt] == m-l+1)
     28         l0[rt] += l0[rt*2+1];
     29     if(r0[rt] == r-m)
     30         r0[rt] += r0[rt*2];
     31     //最大的长度为左右子区间最大长度的最大值,与该区间中间的长度取最值 
     32     m1[rt] = max(r1[rt*2]+l1[rt*2+1],max(m1[rt*2],m1[rt*2+1]));
     33     m0[rt] = max(r0[rt*2]+l0[rt*2+1],max(m0[rt*2],m0[rt*2+1]));
     34 }
     35 void pushdown(int l,int r,int rt){
     36     if(lazy[rt]){
     37         lazy[rt*2] ^= 1;
     38         lazy[rt*2+1] ^= 1;
     39         lazy[rt] = 0;
     40         change(rt*2);
     41         change(rt*2+1);
     42     }
     43 }
     44 void build(int l,int r,int rt){
     45     m1[rt] = m0[rt] = l1[rt] = r1[rt] = l0[rt] = r0[rt] = lazy[rt] = 0;;
     46     if(l == r){
     47         scanf("%d",&m1[rt]);
     48         if(m1[rt] == 1)
     49             l1[rt] = r1[rt] = 1;
     50         else
     51             l0[rt] = r0[rt] = m0[rt] = 1;
     52         return;
     53     }
     54     int m = (l+r)/2;
     55     build(lson);
     56     build(rson);
     57     pushup(l,r,rt);
     58 }
     59 void update(int l,int r,int rt,int a,int b){
     60     if(a<=l && b>=r){
     61         lazy[rt] ^= 1;
     62         change(rt);
     63         return;
     64     }
     65     pushdown(l,r,rt);
     66     int m = (l+r)/2;
     67     if(a <= m)
     68         update(lson,a,b);
     69     if(b > m)
     70         update(rson,a,b);
     71     pushup(l,r,rt);
     72 }
     73 int query(int l,int r,int rt,int a,int b){
     74     if(a<=l && b>=r){
     75         return m1[rt];
     76     }
     77     pushdown(l,r,rt);
     78     int m = (l+r)/2;
     79     if(b <= m)
     80         return query(lson,a,b);
     81     if(a > m)
     82         return query(rson,a,b);
     83     int t1 = query(lson,a,b);
     84     int t2 = query(rson,a,b);
     85     //最值在左半区间、右半区间、以及中间的长度里去,其中中间的长度不能大于查询长度的边界 
     86     return max(max(t1,t2),min(m-a+1,r1[rt*2])+min(b-m,l1[rt*2+1]));
     87 }
     88 int main(){
     89     int n;
     90     while(scanf("%d",&n)!=EOF){
     91         build(1,n,1);
     92         int m;
     93         scanf("%d",&m);
     94         int x,a,b;
     95         while(m--){
     96             scanf("%d%d%d",&x,&a,&b);
     97             if(x == 0){
     98                 printf("%d
    ",query(1,n,1,a,b));
     99             }else{
    100                 update(1,n,1,a,b);
    101             }
    102         }
    103     }
    104     return 0;
    105 } 
  • 相关阅读:
    【FFMPEG】ffmpeg 时间戳问题汇总
    【FFMPEG】基于RTP的H264视频数据打包解包类
    【FFMPEG】基于RTP的H264视频数据打包解包类
    【FFMPEG】使用FFMPEG+H264实现RTP传输数据
    【FFMPEG】使用FFMPEG+H264实现RTP传输数据
    【FFMPEG】谈谈RTP传输中的负载类型和时间戳
    【FFMPEG】谈谈RTP传输中的负载类型和时间戳
    【图像处理】FFmpeg解码H264及swscale缩放详解
    【图像处理】FFmpeg解码H264及swscale缩放详解
    【图像处理】FFmpeg-0
  • 原文地址:https://www.cnblogs.com/zqy123/p/5391980.html
Copyright © 2020-2023  润新知