[SCOI 2010] 序列操作
[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=1858
[算法]
用线段树维护 :
1. 区间中1的个数
2. 左端点向右延伸最长连续1的长度
3. 右端点向左延伸最长连续1的长度
4. 左端点向右延伸最长连续0的长度
5. 右端点向左延伸最长连续0的长度
6. 区间中最多有多少个连续的1
细节较为繁琐 , 写代码时要严谨
时间复杂度 : O(NlogN)
[代码]
#include<bits/stdc++.h> using namespace std; #define MAXN 100010 typedef long long ll; typedef long double ld; int n , q; int a[MAXN]; template <typename T> inline void chkmax(T &x,T y) { x = max(x,y); } template <typename T> inline void chkmin(T &x,T y) { x = min(x,y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == '-') f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0'; x *= f; } struct Segment_Tree { struct Node { int l , r; int lm0 , rm0 , lm1 , rm1 , value0 , value1 , cnt; int taga , tagb; } Tree[MAXN << 2]; inline void update(int index) { int l = Tree[index].l , r = Tree[index].r; int mid = (l + r) >> 1; Tree[index].cnt = Tree[index << 1].cnt + Tree[index << 1 | 1].cnt; if (Tree[index << 1].cnt == mid - l + 1) Tree[index].lm1 = mid - l + 1 + Tree[index << 1 | 1].lm1; else Tree[index].lm1 = Tree[index << 1].lm1; if (Tree[index << 1 | 1].cnt == r - mid) Tree[index].rm1 = r - mid + Tree[index << 1].rm1; else Tree[index].rm1 = Tree[index << 1 | 1].rm1; if (Tree[index << 1].cnt == 0) Tree[index].lm0 = mid - l + 1 + Tree[index << 1 | 1].lm0; else Tree[index].lm0 = Tree[index << 1].lm0; if (Tree[index << 1 | 1].cnt == 0) Tree[index].rm0 = r - mid + Tree[index << 1].rm0; else Tree[index].rm0 = Tree[index << 1 | 1].rm0; Tree[index].value0 = max(Tree[index << 1].value0 , Tree[index << 1 | 1].value0); chkmax(Tree[index].value0 , Tree[index << 1].rm0 + Tree[index << 1 | 1].lm0); Tree[index].value1 = max(Tree[index << 1].value1 , Tree[index << 1 | 1].value1); chkmax(Tree[index].value1 , Tree[index << 1].rm1 + Tree[index << 1 | 1].lm1); } inline void pushdown(int index) { int l = Tree[index].l , r = Tree[index].r; int mid = (l + r) >> 1; if (Tree[index].taga == 0) { Tree[index << 1].cnt = Tree[index << 1 | 1].cnt = 0; Tree[index << 1].lm1 = Tree[index << 1 | 1].lm1 = 0; Tree[index << 1].rm1 = Tree[index << 1 | 1].rm1 = 0; Tree[index << 1].lm0 = Tree[index << 1].rm0 = mid - l + 1; Tree[index << 1 | 1].lm0 = Tree[index << 1 | 1].rm0 = r - mid; Tree[index << 1].value0 = mid - l + 1; Tree[index << 1 | 1].value0 = r - mid; Tree[index << 1].value1 = Tree[index << 1 | 1].value1 = 0; Tree[index << 1].taga = Tree[index << 1 | 1].taga = 0; Tree[index << 1].tagb = Tree[index << 1 | 1].tagb = 0; Tree[index].taga = -1; } else if (Tree[index].taga == 1) { Tree[index << 1].cnt = mid - l + 1; Tree[index << 1 | 1].cnt = r - mid; Tree[index << 1].lm1 = Tree[index << 1].rm1 = mid - l + 1; Tree[index << 1].lm0 = Tree[index << 1].rm0 = 0; Tree[index << 1 | 1].lm0 = Tree[index << 1 | 1].rm0 = 0; Tree[index << 1 | 1].lm1 = Tree[index << 1 | 1].rm1 = r - mid; Tree[index << 1].value0 = Tree[index << 1 | 1].value0 = 0; Tree[index << 1].value1 = mid - l + 1; Tree[index << 1 | 1].value1 = r - mid; Tree[index << 1].taga = Tree[index << 1 | 1].taga = 1; Tree[index << 1].tagb = Tree[index << 1 | 1].tagb = 0; Tree[index].taga = -1; } if (Tree[index].tagb) { Tree[index << 1].cnt = (mid - l + 1) - Tree[index << 1].cnt; Tree[index << 1 | 1].cnt = (r - mid) - Tree[index << 1 | 1].cnt; swap(Tree[index << 1].value0 , Tree[index << 1].value1); swap(Tree[index << 1 | 1].value0 , Tree[index << 1 | 1].value1); swap(Tree[index << 1].lm0 , Tree[index << 1].lm1); swap(Tree[index << 1].rm0 , Tree[index << 1].rm1); swap(Tree[index << 1 | 1].lm0 , Tree[index << 1 | 1].lm1); swap(Tree[index << 1 | 1].rm0 , Tree[index << 1 | 1].rm1); Tree[index << 1].tagb ^= 1; Tree[index << 1 | 1].tagb ^= 1; Tree[index].tagb = 0; } } inline void build(int index , int l , int r) { Tree[index].l = l; Tree[index].r = r; Tree[index].taga = -1; Tree[index].tagb = 0; if (l == r) { if (a[l] == 0) { Tree[index].lm0 = Tree[index].rm0 = 1; Tree[index].value0 = 1; } else { Tree[index].lm1 = Tree[index].rm1 = 1; Tree[index].value1 = 1; Tree[index].cnt = 1; } return; } int mid = (l + r) >> 1; build(index << 1 , l , mid); build(index << 1 | 1 , mid + 1 , r); update(index); } inline void modify(int index , int l , int r , int value) { if (Tree[index].l == l && Tree[index].r == r) { if (value == 0) { Tree[index].lm1 = Tree[index].rm1 = 0; Tree[index].lm0 = Tree[index].rm0 = r - l + 1; Tree[index].cnt = 0; Tree[index].value0 = r - l + 1; Tree[index].value1 = 0; Tree[index].taga = value; Tree[index].tagb = 0; } else { Tree[index].lm0 = Tree[index].rm0 = 0; Tree[index].lm1 = Tree[index].rm1 = r - l + 1; Tree[index].cnt = r - l + 1; Tree[index].value0 = 0; Tree[index].value1 = r - l + 1; Tree[index].taga = value; Tree[index].tagb = 0; } return; } pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) modify(index << 1 , l , r , value); else if (mid + 1 <= l) modify(index << 1 | 1 , l , r , value); else { modify(index << 1 , l , mid , value); modify(index << 1 | 1 , mid + 1 , r , value); } update(index); } inline void reverse(int index , int l , int r) { if (Tree[index].l == l && Tree[index].r == r) { Tree[index].cnt = (r - l + 1) - Tree[index].cnt; swap(Tree[index].lm0 , Tree[index].lm1); swap(Tree[index].rm0 , Tree[index].rm1); swap(Tree[index].value0 , Tree[index].value1); Tree[index].tagb ^= 1; return; } pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) reverse(index << 1 , l , r); else if (mid + 1 <= l) reverse(index << 1 | 1 , l , r); else { reverse(index << 1 , l , mid); reverse(index << 1 | 1 , mid + 1 , r); } update(index); } inline int queryA(int index , int l , int r) { if (Tree[index].l == l && Tree[index].r == r) return Tree[index].cnt; pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) return queryA(index << 1 , l , r); else if (mid + 1 <= l) return queryA(index << 1 | 1 , l , r); else return queryA(index << 1 , l , mid) + queryA(index << 1 | 1 , mid + 1 , r); } inline int queryB(int index , int l , int r) { if (Tree[index].l == l && Tree[index].r == r) return Tree[index].value1; pushdown(index); int mid = (Tree[index].l + Tree[index].r) >> 1; if (mid >= r) return queryB(index << 1 , l , r); else if (mid + 1 <= l) return queryB(index << 1 | 1 , l , r); else { int ret = max(queryB(index << 1 , l , mid) , queryB(index << 1 | 1 , mid + 1 , r)); chkmax(ret , min(mid - l + 1 , Tree[index << 1].rm1) + min(r - mid , Tree[index << 1 | 1].lm1)); return ret; } } } SGT; int main() { read(n); read(q); for (int i = 1; i <= n; i++) read(a[i]); SGT.build(1 , 1 , n); while (q--) { int type; read(type); if (type == 0) { int l , r; read(l); read(r); ++l; ++r; SGT.modify(1 , l , r , 0); } else if (type == 1) { int l , r; read(l); read(r); ++l; ++r; SGT.modify(1 , l , r , 1); } else if (type == 2) { int l , r; read(l); read(r); ++l; ++r; SGT.reverse(1 , l , r); } else if (type == 3) { int l , r; read(l); read(r); ++l; ++r; printf("%d\n" , SGT.queryA(1 , l , r)); } else { int l , r; read(l); read(r); ++l; ++r; printf("%d\n" , SGT.queryB(1 , l , r)); } } return 0; }