题目链接:

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不可以用于函数,尤其是递归函数,这样会使得同一函数重复调用好几遍,递归函数的话更会超时。

 #include<bits/stdc++.h>
#define IOS ios::sync_with_stdio(false);//不可再使用scanf printf
#define Max(a, b) ((a) > (b) ? (a) : (b))//禁用于函数,会超时
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Mem(a) memset(a, 0, sizeof(a))
#define Dis(x, y, x1, y1) ((x - x1) * (x - x1) + (y - y1) * (y - y1))
#define MID(l, r) ((l) + ((r) - (l)) / 2)
#define lson ((o)<<1)
#define rson ((o)<<1|1)
#pragma comment(linker, "/STACK:102400000,102400000")//栈外挂
using namespace std;
inline int read()
{
int x=,f=;char ch=getchar();
while (ch<''||ch>''){if (ch=='-') f=-;ch=getchar();}
while (ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
return x*f;
} typedef long long ll;
const int maxn = + ;
const int MOD = ;//const引用更快,宏定义也更快 struct node
{
int l, r;//左右区间
int ls0, rs0, ms0;//左连续的0,右连续的0,区间最大连续的0
int ls1, rs1, ms1;//左连续的1,右连续的1,区间最大连续的1
int sum0, sum1;//区间0 1数目
int lazy, Xor;//懒惰标记和异或标记
}tree[maxn << ];
int a[maxn];
void pushup(int o)
{
if(tree[o].l == tree[o].r)return;//叶子节点直接返回
//根据子节点的信息,更新父节点信息 //更新0:
int lc = lson, rc = rson;
tree[o].ls0 = tree[lc].ls0;
tree[o].rs0 = tree[rc].rs0;
if(tree[lc].ls0 == tree[lc].r - tree[lc].l + )
tree[o].ls0 += tree[rc].ls0;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
if(tree[rc].rs0 == tree[rc].r - tree[rc].l + )
tree[o].rs0 += tree[lc].rs0;
tree[o].ms0 = Max(Max(tree[lc].ms0, tree[rc].ms0), tree[lc].rs0 + tree[rc].ls0);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
tree[o].sum0 = tree[lc].sum0 + tree[rc].sum0;
//更新1
tree[o].ls1 = tree[lc].ls1;
tree[o].rs1 = tree[rc].rs1;
if(tree[lc].ls1 == tree[lc].r - tree[lc].l + )
tree[o].ls1 += tree[rc].ls1;//左节点左连续的0为区间长度 那么根节点左连续的0需要再加上右节点左连续的0
if(tree[rc].rs1 == tree[rc].r - tree[rc].l + )
tree[o].rs1 += tree[lc].rs1;
tree[o].ms1 = Max(Max(tree[lc].ms1, tree[rc].ms1), tree[lc].rs1 + tree[rc].ls1);//最大连续0 = Max(左节点最大连续0, 右节点最大连续0,中间最大连续0)
tree[o].sum1 = tree[lc].sum1 + tree[rc].sum1;
}
void XOR(int o)
{
swap(tree[o].ls0, tree[o].ls1);
swap(tree[o].rs0, tree[o].rs1);
swap(tree[o].ms0, tree[o].ms1);
swap(tree[o].sum0, tree[o].sum1);
}
void pushdown(int o)//标记下传
{
if(tree[o].l == tree[o].r)return;
if(tree[o].lazy != -)//区间覆盖0或者1
{
int lc = lson, rc = rson, len = tree[o].r - tree[o].l + ;
tree[lc].lazy = tree[rc].lazy = tree[o].lazy;
tree[lc].Xor = tree[rc].Xor = ; //左节点长度为(len+1) / 2 右节点长度为len/2
//左
tree[lc].ls0 = tree[lc].rs0 = tree[lc].ms0 = tree[o].lazy ? : (len + ) / ;
tree[lc].ls1 = tree[lc].rs1 = tree[lc].ms1 = tree[o].lazy ? (len + ) / : ;
tree[lc].sum0 = tree[o].lazy ? : (len + ) / ;
tree[lc].sum1 = tree[o].lazy ? (len + ) / : ;
//右
tree[rc].ls0 = tree[rc].rs0 = tree[rc].ms0 = tree[o].lazy ? : (len) / ;
tree[rc].ls1 = tree[rc].rs1 = tree[rc].ms1 = tree[o].lazy ? (len) / : ;
tree[rc].sum0 = tree[o].lazy ? : (len) / ;
tree[rc].sum1 = tree[o].lazy ? (len) / : ; tree[o].lazy = -;//清除标记
}
if(tree[o].Xor)
{
tree[o].Xor = ;
tree[lson].Xor ^= ;
tree[rson].Xor ^= ;
XOR(lson), XOR(rson);
}
}
void build(int o, int l, int r)
{
tree[o].l = l, tree[o].r = r, tree[o].lazy = -, tree[o].Xor = ;
if(l == r)
{
tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = (a[l] == );
tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = (a[l] == );
tree[o].sum1 = (a[l] == );
tree[o].sum0 = (a[l] == );
return;
}
int m = MID(l, r);
build(lson, l, m);
build(rson, m + , r);
pushup(o);
}
int flag;//标记类型
int ql, qr;
void update(int o)
{
pushdown(o);
if(ql <= tree[o].l && qr >= tree[o].r)
{
if(flag == )
{
tree[o].Xor = ;
XOR(o);
}
else
{
int len = tree[o].r - tree[o].l + ;
tree[o].lazy = flag;
tree[o].ls0 = tree[o].rs0 = tree[o].ms0 = flag ? : len;
tree[o].ls1 = tree[o].rs1 = tree[o].ms1 = flag ? len : ;
tree[o].sum0 = flag ? : len;
tree[o].sum1 = flag ? len : ;
}
}
else
{
int m = MID(tree[o].l, tree[o].r);
if(ql <= m)update(lson);
if(qr > m)update(rson);
pushup(o);
}
} int query(int o)
{
pushdown(o);
if(ql <= tree[o].l && qr >= tree[o].r)
{
if(flag == )return tree[o].sum1;
else return tree[o].ms1;
}
else
{
if(qr <= tree[lson].r)return query(lson);
if(ql >= tree[rson].l)return query(rson);
if(flag == )return query(lson) + query(rson);
int ans1 = Min(tree[lson].rs1, tree[lson].r - ql + ) + Min(tree[rson].ls1, qr - tree[rson].l + );
int ans2 = max(query(lson), query(rson));//用宏定义会超时,因为一直在递归
return Max(ans1, ans2);
}
} int main()
{
int T;
scanf("%d", &T);
while(T--)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i = ; i <= n; i++)scanf("%d", &a[i]);
build(, , n);
while(m--)
{
scanf("%d%d%d", &flag, &ql, &qr);
ql++, qr++;
if(flag < )update();
else printf("%d\n", query());
}
}
return ;
}

hdu-3397 Sequence operation 线段树多种标记的更多相关文章

  1. hdu 3397 Sequence operation (线段树 区间合并 多重标记)

    链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问 ...

  2. hdu 3397 Sequence operation 线段树

    题目链接 给出n个数, 每个数是0或1, 给5种操作, 区间变为1, 区间变为0, 区间0,1翻转, 询问区间内1的个数, 询问区间内最长连续1的个数. 需要将数组开成二维的, 然后区间0, 1翻转只 ...

  3. hdu 3397 Sequence operation 线段树 区间更新 区间合并

    题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b ...

  4. HDU 3397 Sequence operation(线段树)

    HDU 3397 Sequence operation 题目链接 题意:给定一个01序列,有5种操作 0 a b [a.b]区间置为0 1 a b [a,b]区间置为1 2 a b [a,b]区间0变 ...

  5. hdu 3397 Sequence operation(线段树:区间更新)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的 ...

  6. hdu 3397 Sequence operation(很有意思的线段树题)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  7. 【线段树】HDU 3397 Sequence operation 区间合并

    操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters i ...

  8. Sequence operation(线段树区间多种操作)

    Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Othe ...

  9. hdu3397 Sequence operation 线段树

    hdu3397 Sequence operation #include <bits/stdc++.h> using namespace std; ; struct node { /// l ...

随机推荐

  1. webpack 报错 No PostCSS Config found 解决方案。

    webpack 报错 No PostCSS Config found  这个问题我在百度上找了好久,也没有找到解决方案,最后没有办法只能自己去啃官方文档,本案例在本人的webpack 学习感悟中已经写 ...

  2. C# 多维数组

    int[, ,] shuzu = new int[4, 3, 2]; //有四个二维数组,每个二维数组里面有3个1维数组,每个1维数组里面有2个元素

  3. redis中的发布订阅(Pub/Sub)

    这里使用nodejs的redis模块说明,具体可见https://www.npmjs.com/package/redis,先来通过一个简单的例子了解下redis中的Pub/Sub具体怎么实现吧.. v ...

  4. flask中的数据操作

    flask中数据访问: pip install flask-sqlalemy 创建数据: 创建app的工厂 from flask import Flask from flask_sqlalchemy ...

  5. Echarts 使用asp.net +ashx+ajax 实现 饼图、柱形图后台交互

    向上效果图 前端code /* * ------------------------------------------------------------------ * module-inform ...

  6. xshell 中解决中文乱码问题

    点击菜单栏 文件 -> 属性 在属性对话框内点击终端, 选择 编码为 UTF-8 即可.

  7. K:大数加法

    相关介绍:  在java中,整数是有最大上限的.所谓大数是指超过整数最大上限的数,例如18 452 543 389 943 209 789 324 233和8 123 534 323 432 323 ...

  8. PAT 1032. Sharing

    其实就是链表求交: #include <iostream> #include <cstdio> #include <cstdlib> #include <un ...

  9. UOJ#316. 【NOI2017】泳池

    传送门 一道 \(DP\) 好题 设 \(q\) 为一个块合法的概率 套路一恰好为 \(k\) 的概率不好算,算小于等于 \(k\) 的减去小于等于 \(k-1\) 的 那么设 \(f_i\) 表示宽 ...

  10. 使用iview时,页面没了滚动条

    场景:页面中有一个确认按钮,保存后弹框预览在点保存按钮,实现数据提交.提交后回到数据列表页,用this.$router.push('list'),返回后页面无法滚动了. 原因:排查后发现弹框时在bod ...