zoukankan      html  css  js  c++  java
  • hdu-3397 Sequence operation 线段树多种标记

    题目链接:

    http://acm.hdu.edu.cn/showproblem.php?pid=3397

    题目大意:

    0 a b表示a-b区间置为0

    1 a b表示a-b区间置为1

    2 a b表示a-b区间中的0变成1,1变成0

    3 a b表示a-b区间中的1的数目

    4 a b表示a-b区间中最长连续1的长度

    解题思路:

    线段树多种标记。

    需要处理的东西比较多:

    做题的时候发现一个问题:

    我的宏定义Max不可以用于函数,尤其是递归函数,这样会使得同一函数重复调用好几遍,递归函数的话更会超时。

      1 #include<bits/stdc++.h>
      2 #define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
      3 #define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
      4 #define Min(a, b) ((a) < (b) ? (a) : (b))
      5 #define Mem(a) memset(a, 0, sizeof(a))
      6 #define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
      7 #define MID(l, r) ((l) + ((r) - (l)) / 2)
      8 #define lson ((o)<<1)
      9 #define rson ((o)<<1|1)
     10 #pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
     11 using namespace std;
     12 inline int read()
     13 {
     14     int x=0,f=1;char ch=getchar();
     15     while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
     16     while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
     17     return x*f;
     18 }
     19 
     20 typedef long long ll;
     21 const int maxn = 100000 + 10;
     22 const int MOD = 1000000007;//const引用更快,宏定义也更快
     23 
     24 struct node
     25 {
     26     int l, r;//左右区间
     27     int ls0, rs0, ms0;//左连续的0,右连续的0,区间最大连续的0
     28     int ls1, rs1, ms1;//左连续的1,右连续的1,区间最大连续的1
     29     int sum0, sum1;//区间0 1数目
     30     int lazy, Xor;//懒惰标记和异或标记
     31 }tree[maxn << 2];
     32 int a[maxn];
     33 void pushup(int o)
     34 {
     35     if(tree[o].l == tree[o].r)return;//叶子节点直接返回
     36     //根据子节点的信息,更新父节点信息
     37 
     38     //更新0:
     39     int lc = lson, rc = rson;
     40     tree[o].ls0 = tree[lc].ls0;
     41     tree[o].rs0 = tree[rc].rs0;
     42     if(tree[lc].ls0 == tree[lc].r - tree[lc].l + 1)
     43         tree[o].ls0 += tree[rc].ls0;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
     44     if(tree[rc].rs0 == tree[rc].r - tree[rc].l + 1)
     45         tree[o].rs0 += tree[lc].rs0;
     46     tree[o].ms0 = Max(Max(tree[lc].ms0, tree[rc].ms0), tree[lc].rs0 + tree[rc].ls0);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
     47     tree[o].sum0 = tree[lc].sum0 + tree[rc].sum0;
     48     //更新1
     49     tree[o].ls1 = tree[lc].ls1;
     50     tree[o].rs1 = tree[rc].rs1;
     51     if(tree[lc].ls1 == tree[lc].r - tree[lc].l + 1)
     52         tree[o].ls1 += tree[rc].ls1;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
     53     if(tree[rc].rs1 == tree[rc].r - tree[rc].l + 1)
     54         tree[o].rs1 += tree[lc].rs1;
     55     tree[o].ms1 = Max(Max(tree[lc].ms1, tree[rc].ms1), tree[lc].rs1 + tree[rc].ls1);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
     56     tree[o].sum1 = tree[lc].sum1 + tree[rc].sum1;
     57 }
     58 void XOR(int o)
     59 {
     60     swap(tree[o].ls0, tree[o].ls1);
     61     swap(tree[o].rs0, tree[o].rs1);
     62     swap(tree[o].ms0, tree[o].ms1);
     63     swap(tree[o].sum0, tree[o].sum1);
     64 }
     65 void pushdown(int o)//标记下传
     66 {
     67     if(tree[o].l == tree[o].r)return;
     68     if(tree[o].lazy != -1)//区间覆盖0或者1
     69     {
     70         int lc = lson, rc = rson, len = tree[o].r - tree[o].l + 1;
     71         tree[lc].lazy = tree[rc].lazy = tree[o].lazy;
     72         tree[lc].Xor = tree[rc].Xor = 0;
     73 
     74         //左节点长度为(len+1) / 2 右节点长度为len/2
     75         //
     76         tree[lc].ls0 = tree[lc].rs0 = tree[lc].ms0 = tree[o].lazy ? 0 : (len + 1) / 2;
     77         tree[lc].ls1 = tree[lc].rs1 = tree[lc].ms1 = tree[o].lazy ? (len + 1) / 2 : 0;
     78         tree[lc].sum0 = tree[o].lazy ? 0 : (len + 1) / 2;
     79         tree[lc].sum1 = tree[o].lazy ? (len + 1) / 2 : 0;
     80         //
     81         tree[rc].ls0 = tree[rc].rs0 = tree[rc].ms0 = tree[o].lazy ? 0 : (len) / 2;
     82         tree[rc].ls1 = tree[rc].rs1 = tree[rc].ms1 = tree[o].lazy ? (len) / 2 : 0;
     83         tree[rc].sum0 = tree[o].lazy ? 0 : (len) / 2;
     84         tree[rc].sum1 = tree[o].lazy ? (len) / 2 : 0;
     85 
     86         tree[o].lazy = -1;//清除标记
     87     }
     88     if(tree[o].Xor)
     89     {
     90         tree[o].Xor = 0;
     91         tree[lson].Xor ^= 1;
     92         tree[rson].Xor ^= 1;
     93         XOR(lson), XOR(rson);
     94     }
     95 }
     96 void build(int o, int l, int r)
     97 {
     98     tree[o].l = l, tree[o].r = r, tree[o].lazy = -1, tree[o].Xor = 0;
     99     if(l == r)
    100     {
    101         tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = (a[l] == 0);
    102         tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = (a[l] == 1);
    103         tree[o].sum1 = (a[l] == 1);
    104         tree[o].sum0 = (a[l] == 0);
    105         return;
    106     }
    107     int m = MID(l, r);
    108     build(lson, l, m);
    109     build(rson, m + 1, r);
    110     pushup(o);
    111 }
    112 int flag;//标记类型
    113 int ql, qr;
    114 void update(int o)
    115 {
    116     pushdown(o);
    117     if(ql <= tree[o].l && qr >= tree[o].r)
    118     {
    119         if(flag == 2)
    120         {
    121             tree[o].Xor = 1;
    122             XOR(o);
    123         }
    124         else
    125         {
    126             int len = tree[o].r - tree[o].l + 1;
    127             tree[o].lazy = flag;
    128             tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = flag ? 0 : len;
    129             tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = flag ? len : 0;
    130             tree[o].sum0 = flag ? 0 : len;
    131             tree[o].sum1 = flag ? len : 0;
    132         }
    133     }
    134     else
    135     {
    136         int m = MID(tree[o].l, tree[o].r);
    137         if(ql <= m)update(lson);
    138         if(qr > m)update(rson);
    139         pushup(o);
    140     }
    141 }
    142 
    143 int query(int o)
    144 {
    145     pushdown(o);
    146     if(ql <= tree[o].l && qr >= tree[o].r)
    147     {
    148         if(flag == 3)return tree[o].sum1;
    149         else return tree[o].ms1;
    150     }
    151     else
    152     {
    153         if(qr <= tree[lson].r)return query(lson);
    154         if(ql >= tree[rson].l)return query(rson);
    155         if(flag == 3)return query(lson) + query(rson);
    156         int ans1 = Min(tree[lson].rs1, tree[lson].r - ql + 1) + Min(tree[rson].ls1, qr - tree[rson].l + 1);
    157         int ans2 = max(query(lson), query(rson));//用宏定义会超时,因为一直在递归
    158         return Max(ans1, ans2);
    159     }
    160 }
    161 
    162 int main()
    163 {
    164     int T;
    165     scanf("%d", &T);
    166     while(T--)
    167     {
    168         int n, m;
    169         scanf("%d%d", &n, &m);
    170         for(int i = 1; i <= n; i++)scanf("%d", &a[i]);
    171         build(1, 1, n);
    172         while(m--)
    173         {
    174             scanf("%d%d%d", &flag, &ql, &qr);
    175             ql++, qr++;
    176             if(flag < 3)update(1);
    177             else printf("%d
    ", query(1));
    178         }
    179     }
    180     return 0;
    181 }
  • 相关阅读:
    递延收益为什么属于负债类科目
    java 环境变量脚本
    dotnet 执行命令常用代码
    centos安装nuget
    centos 安装nodejs redis
    linux git 记住密码
    libgit2-6311e88: cannot open shared object file: No such file or directory
    angular ng build 报错 Cannot read property 'default' of undefined
    java ObjectMapper json 与对象的相互转换
    java 流不能复用 stream has already been operated upon or closed 内存分页
  • 原文地址:https://www.cnblogs.com/fzl194/p/9567091.html
Copyright © 2011-2022 走看看