HDU 3397 Sequence operation 线段树

线段树大杂烩~ 各种操作都有,细心点不难1A

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

#define lson rt<<1,l,mid
#define rson rt<<1|1,mid + 1,r
const int maxn = 1e5 + 10;
int lmax[maxn << 2][2], rmax[maxn << 2][2], mmax[maxn << 2][2];
int lazy_xor[maxn << 2], lazy_cover[maxn << 2], sum[maxn << 2];
int N, M, val[maxn];

void swap(int &a, int &b) {
	int t = a; a = b; b = t;
}

void change_xor(int rt, int l, int r) {
	swap(lmax[rt][0], lmax[rt][1]);
	swap(rmax[rt][0], rmax[rt][1]);
	swap(mmax[rt][0], mmax[rt][1]);
	sum[rt] = r - l + 1 - sum[rt];
}

void change_cover(int rt, int l, int r, int Val) {
	for (int i = 0; i < 2; i++)
		lmax[rt][i] = rmax[rt][i] = mmax[rt][i] =
			Val == i ? r - l + 1 : 0;
	sum[rt] = Val * (r - l + 1);
}

void pushup(int rt, int l, int r) {
	int lc = rt << 1, rc = rt << 1 | 1, mid = (l + r) >> 1;
	int Llen = mid - l + 1, Rlen = r - mid;
	for (int i = 0; i < 2; i++) {
		lmax[rt][i] = lmax[lc][i];
		rmax[rt][i] = rmax[rc][i];
		mmax[rt][i] = max(mmax[lc][i], mmax[rc][i]);
		if (lmax[rc][i] != 0 && rmax[lc][i] != 0) {
			if (lmax[lc][i] == Llen)
				lmax[rt][i] += lmax[rc][i];
			if (rmax[rc][i] == Rlen)
				rmax[rt][i] += rmax[lc][i];
			mmax[rt][i] = max(mmax[rt][i], rmax[lc][i] + lmax[rc][i]);
			mmax[rt][i] = max(mmax[rt][i], lmax[rt][i]);
			mmax[rt][i] = max(mmax[rt][i], rmax[rt][i]);
		}
	}
	sum[rt] = sum[lc] + sum[rc];
}

void pushdown_cover(int rt, int l, int r) {
	int lc = rt << 1, rc = rt << 1 | 1, mid = (l + r) >> 1;
	lazy_cover[lc] = lazy_cover[rc] = lazy_cover[rt];
	lazy_xor[lc] = lazy_xor[rc] = 0;
	change_cover(lson, lazy_cover[rt]);
	change_cover(rson, lazy_cover[rt]);
	lazy_cover[rt] = -1;
}

void pushdown_xor(int rt, int l, int r) {
	int lc = rt << 1, rc = rt << 1 | 1, mid = (l + r) >> 1;
	if (lazy_cover[lc] == -1) lazy_xor[lc] ^= 1, change_xor(lson);
	else lazy_cover[lc] ^= 1, change_cover(lson,lazy_cover[lc]);
	if (lazy_cover[rc] == -1) lazy_xor[rc] ^= 1, change_xor(rson);
	else lazy_cover[rc] ^= 1, change_cover(rson, lazy_cover[rc]);
	lazy_xor[rt] = 0;
}

void pushdown(int rt, int l, int r) {
	if (lazy_cover[rt] != -1) pushdown_cover(rt, l, r);
	if (lazy_xor[rt] != 0) pushdown_xor(rt, l, r);
}

void build(int rt, int l, int r) {
	int mid = (l + r) >> 1;
	if (l == r) {
		change_cover(rt, l, r, val[l]);
		lazy_cover[rt] = -1; lazy_xor[rt] = 0;
		sum[rt] = val[l];
	}
	else {
		lazy_cover[rt] = -1; lazy_xor[rt] = 0;
		build(lson); build(rson);
		pushup(rt, l, r);
	}
}

void update(int rt, int l, int r, int ql, int qr, int Val) {
	if (ql <= l && qr >= r) {
		if (Val == 2) {
			if (lazy_cover[rt] == -1) {
				change_xor(rt, l, r); lazy_xor[rt] ^= 1;
			}
			else {
				lazy_cover[rt] ^= 1;
				change_cover(rt,l,r,lazy_cover[rt]);
			}
		}
		else {
			lazy_cover[rt] = Val; lazy_xor[rt] = 0;
			change_cover(rt, l, r, lazy_cover[rt]);
		}
	}
	else {
		int mid = (l + r) >> 1;
		pushdown(rt, l, r);
		if (ql <= mid) update(lson, ql, qr, Val);
		if (qr > mid) update(rson, ql, qr, Val);
		pushup(rt, l, r);
	}
}

int query_sum(int rt, int l, int r, int ql, int qr) {
	if (ql <= l && qr >= r) return sum[rt];
	pushdown(rt, l, r);
	int mid = (l + r) >> 1, ret = 0;
	if (ql <= mid) ret += query_sum(lson, ql, qr);
	if (qr > mid) ret += query_sum(rson, ql, qr);
	return ret;
}

int query_len(int rt, int l, int r, int ql, int qr) {
	int mid = (l + r) >> 1, lc = rt << 1, rc = rt << 1 | 1;
	if (ql <= l && qr >= r) return mmax[rt][1];
	pushdown(rt, l, r);
	if (ql > mid) return query_len(rson, ql, qr);
	if (qr <= mid) return query_len(lson, ql, qr);
	//如果最长的连续出现在左边或者右边
	int Lmax = query_len(lson, ql, mid), Rmax = query_len(rson, mid + 1, qr);
	//或者是出现在中间
	int Lpos, Rpos, Mmax;
	Lpos = max(ql, mid - rmax[lc][1] + 1);
	Rpos = min(qr, mid + lmax[rc][1]);
	Mmax = Rpos - Lpos + 1;
	return max(Mmax, max(Lmax, Rmax));
}

void Handle(int cmd, int a, int b) {
	if (cmd == 0 || cmd == 1 || cmd == 2) update(1, 1, N, a, b, cmd);
	if (cmd == 3) printf("%d\n", query_sum(1, 1, N, a, b));
	if (cmd == 4) printf("%d\n", query_len(1, 1, N, a, b));
}

int main() {
	int T; scanf("%d", &T);
	for (int kase = 1; kase <= T; kase++) {
		scanf("%d%d", &N, &M);
		for (int i = 1; i <= N; i++) scanf("%d", &val[i]);
		build(1, 1, N);
		for (int i = 0; i < M; i++) {
			int cmd, a, b;
			scanf("%d%d%d", &cmd, &a, &b);
			Handle(cmd, a + 1, b + 1);
		}
	}
	return 0;
}

  

HDU 3397 Sequence operation 线段树

时间: 2024-10-20 12:05:50

HDU 3397 Sequence operation 线段树的相关文章

HDU 3397 Sequence operation (线段树,成段更新,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3397 Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5801    Accepted Submission(s): 1713 Problem Description lxhgww got a sequence

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

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问区间1的个数 4.询问区间被最长连续1的长度 思路: 这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表

Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)

Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6397    Accepted Submission(s): 1899 Problem Description lxhgww got a sequence contains n characters which are all '0's or '1

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]中的最长连续1串的长度 这题看题目就很裸,综合了区间更新,区间合并 我一开始把更新操作全放一个变量,但是在push_down的时候很麻烦,情况很多,容易漏,后来改成下面的 更新的操作可以分为两类,一个是置值(stv),一个是互换(swp).如果stv!=-1,则更新儿子节点的stv,并将儿子的sw

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变成1,1变成0 3 a b 查询[a,b]区间1的个数 4 a b 查询[a,b]区间连续1最长的长度 思路:线段树线段合并.须要两个延迟标记一个置为01,一个翻转,然后因为4操作,须要记录左边最长0.1.右边最长0.1,区间最长0.1,然后区间合并去搞就可以 代码: #include <cstdi

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

操作 Change operations: 0 a b change all characters into '0's in [a , b] 1 a b change all characters into '1's in [a , b] 2 a b change all '0's into '1's and change all '1's into '0's in [a, b] Output operations: 3 a b output the number of '1's in [a,

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

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意:给你一个长度为n的0,1序列,支持下列五种操作, 操作0(0 a b):将a到b这个区间的元素全部置为0. 操作1(1 a b):将a到b这个区间的元素全部置为1. 操作2(2 a b):将a到b这个区间所有的0置为1,所有的1置为0. 操作3(3 a b):查询a到b这个区间1的总数. 操作4(4 a b):查询a到b这个区间连续1的最长长度 本题属于简单的区间更新线段树 重点:0操作

HDU 3397 Sequence operation(线段树&#183;成段更新&#183;区间合并&#183;混合操作)

题意  给你一个只有0, 1的数组  有这些操作 0. 将[a, b]区间的所有数都改为0 1. 将[a, b]区间的所有数都改为1 2. 将[a, b]区间的所有数都取反 即与1异或 3. 输出区间[a, b]中1的个数  即所有数的和 4. 输出区间[a, b]中最大连续1的长度 对于所有的3, 4操作输出对应的答案 单个的操作都很简单  但搞在一起就有点恶心了  还好数组里的数只有0和1 线段树维护9个值 对应区间0, 1的最大长度len[i]  对应区间左端点为起点的最大0, 1长度ll

HDU 3397——Sequence operation(线段树,区间染色+区间异或+区间合并)

Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6270    Accepted Submission(s): 1862 Problem Description lxhgww got a sequence contains n characters which are all '0's or '1