[SCOI2010]序列操作 BZOJ1858 线段树
题目描述
lxhgww最近收到了一个01序列,序列里面包含了n个数,这些数要么是0,要么是1,现在对于这个序列有五种变换操作和询问操作:
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
对于每一种询问操作,lxhgww都需要给出回答,聪明的程序员们,你们能帮助他吗?
输入输出格式
输入格式:输入数据第一行包括2个数,n和m,分别表示序列的长度和操作数目
第二行包括n个数,表示序列的初始状态
接下来m行,每行3个数,op, a, b,(0<=op<=4,0<=a<=b<n)表示对于区间[a, b]执行标号为op的操作
输出格式:对于每一个询问操作,输出一行,包括1个数,表示其对应的答案
输入输出样例
输入样例#1:
复制
10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
输出样例#1: 复制
5 2 6 5
说明
对于30%的数据,1<=n, m<=1000
对于100%的数据,1<=n, m<=100000
很刺激的线段树题目;
注意赋值的操作的优先级>翻转的操作;
还有很多细节要注意;
#include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cstring> #include<string> #include<cmath> #include<map> #include<set> #include<vector> #include<queue> #include<bitset> #include<ctime> #include<deque> #include<stack> #include<functional> #include<sstream> //#include<cctype> //#pragma GCC optimize(2) using namespace std; #define maxn 300005 #define inf 0x3f3f3f3f #define INF 9999999999 #define rdint(x) scanf("%d",&x) #define rdllt(x) scanf("%lld",&x) #define rdult(x) scanf("%lu",&x) #define rdlf(x) scanf("%lf",&x) #define rdstr(x) scanf("%s",x) typedef long long ll; typedef unsigned long long ull; typedef unsigned int U; #define ms(x) memset((x),0,sizeof(x)) const long long int mod = 1e9 + 7; #define Mod 1000000000 #define sq(x) (x)*(x) #define eps 1e-3 typedef pair<int, int> pii; #define pi acos(-1.0) const int N = 1005; #define REP(i,n) for(int i=0;i<(n);i++) typedef pair<int, int> pii; inline ll rd() { ll x = 0; char c = getchar(); bool f = false; while (!isdigit(c)) { if (c == '-') f = true; c = getchar(); } while (isdigit(c)) { x = (x << 1) + (x << 3) + (c ^ 48); c = getchar(); } return f ? -x : x; } ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a%b); } ll sqr(ll x) { return x * x; } /*ll ans; ll exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x = 1; y = 0; return a; } ans = exgcd(b, a%b, x, y); ll t = x; x = y; y = t - a / b * y; return ans; } */ ll qpow(ll a, ll b, ll c) { ll ans = 1; a = a % c; while (b) { if (b % 2)ans = ans * a%c; b /= 2; a = a * a%c; } return ans; } struct node { int sum; int Lw, Lb;// Lb:区间连续0的最大长度,Lw:连续1的最大长度 int llw, rlw;//llb:区间左端点连续0的最大长度,llw:区间左端点连续1的最大长度; int llb, rlb;// rlb:区间右端点连续0的最大长度;rlw:区间右端点连续1的最大长度 int lazy, rev;// lazy:是否全部变为1/0;rev:翻转标记 }tr[maxn<<2]; int n, m; #define lson (rt<<1) #define rson (rt<<1|1) #define mid ((l+r)>>1) void pushup(int l, int r, int rt) { tr[rt].sum = tr[lson].sum + tr[rson].sum; tr[rt].Lb = max(tr[lson].Lb, tr[rson].Lb); tr[rt].Lw = max(tr[lson].Lw, tr[rson].Lw); tr[rt].llb = tr[lson].llb; tr[rt].llw = tr[lson].llw; if (tr[lson].llw == mid - l + 1)tr[rt].llw += tr[rson].llw; if (tr[lson].llb == mid - l + 1)tr[rt].llb += tr[rson].llb; tr[rt].rlb = tr[rson].rlb; tr[rt].rlw = tr[rson].rlw; if (tr[rson].rlb == r - mid)tr[rt].rlb += tr[lson].rlb; if (tr[rson].rlw == r - mid)tr[rt].rlw += tr[lson].rlw; tr[rt].Lw = max(tr[rt].Lw, tr[lson].rlw + tr[rson].llw); tr[rt].Lb = max(tr[rt].Lb, tr[lson].rlb + tr[rson].llb); } void down(int l, int r, int rt) { int lazy = tr[rt].lazy, rev = tr[rt].rev; int L1 = mid - l + 1, L2 = r - mid; tr[rt].lazy = -1; if (lazy == 0) { tr[lson] = node { 0, 0, L1, 0, 0, L1, L1, 0, 0 }; tr[rson] = node{ 0,0,L2,0,0,L2,L2,0,0 }; } else if (lazy == 1) { tr[lson] = node{ L1,L1,0,L1,L1,0,0,1,0 }; tr[rson] = node{ L2,L2,0,L2,L2,0,0,1,0 }; } if (rev) { tr[rt].rev = 0; int sum = tr[lson].sum; int Lw = tr[lson].Lw, Lb = tr[lson].Lb; int llw = tr[lson].llw, llb = tr[lson].llb; int rlw = tr[lson].rlw, rlb = tr[lson].rlb; tr[lson].sum = L1 - sum; tr[lson].Lw = Lb; tr[lson].Lb = Lw; tr[lson].llw = llb; tr[lson].rlw = rlb; tr[lson].llb = llw; tr[lson].rlb = rlw; tr[lson].rev ^= 1; sum = tr[rson].sum; Lw = tr[rson].Lw; Lb = tr[rson].Lb; llw = tr[rson].llw; llb = tr[rson].llb; rlw = tr[rson].rlw; rlb = tr[rson].rlb; tr[rson].sum = L2 - sum; tr[rson].Lw = Lb; tr[rson].Lb = Lw; tr[rson].llw = llb; tr[rson].rlw = rlb; tr[rson].llb = llw; tr[rson].rlb = rlw; tr[rson].rev ^= 1; } } void build(int l, int r, int rt) { tr[rt].lazy = -1; if (l == r) { int x; rdint(x); tr[rt] = node{ x,x,(x ^ 1),x,x,(x ^ 1),(x ^ 1),-1,0 }; return; } build(l, mid, lson); build(mid + 1, r, rson); pushup(l, r, rt); } void upd1(int l, int r, int rt, int L, int R) { if (L <= l && r <= R) { int LL = r - l + 1; tr[rt] = node{ 0,0,LL,0,0,LL,LL,0,0 }; return; } if (l > R || r < L)return; down(l, r, rt); upd1(l, mid, lson, L, R); upd1(mid + 1, r, rson, L, R); pushup(l, r, rt); } void upd2(int l, int r, int rt, int L, int R) { if (L <= l && r <= R) { int LL = r - l + 1; tr[rt] = node{ LL,LL,0,LL,LL,0,0,1,0 }; return; } if (l > R || r < L)return; down(l, r, rt); upd2(l, mid, lson, L, R); upd2(mid + 1, r, rson, L, R); pushup(l, r, rt); } void upd3(int l, int r, int rt, int L, int R) { if (L <= l && r <= R) { int LL = r - l + 1, sum = tr[rt].sum, Lw = tr[rt].Lw, Lb = tr[rt].Lb; int llw = tr[rt].llw, llb = tr[rt].llb; int rlw = tr[rt].rlw, rlb = tr[rt].rlb; tr[rt] = node{ LL - sum,Lb,Lw,llb,rlb,llw,rlw,tr[rt].lazy,(tr[rt].rev ^ 1) }; return; } if (l > R || r < L)return; down(l, r, rt); upd3(l, mid, lson, L, R); upd3(mid + 1, r, rson, L, R); pushup(l, r, rt); } int query1(int l, int r, int rt, int L, int R) { if (L <= l && r <= R)return tr[rt].sum; if (l > R || r < L)return 0; down(l, r, rt); return query1(l, mid, lson, L, R) + query1(mid + 1, r, rson, L, R); } node query2(int l, int r, int rt, int L, int R) { if (L <= l && r <= R)return tr[rt]; if (l > R || r < L)return node{ 0 }; down(l, r, rt); node LL = query2(l, mid, lson, L, R), RR = query2(mid + 1, r, rson, L, R), ans; ans.sum = LL.sum + RR.sum; ans.Lw = max(LL.Lw, RR.Lw); ans.Lb = max(LL.Lb, RR.Lb); ans.llw = LL.llw, ans.rlw = RR.rlw; ans.llb = LL.llb, ans.rlb = RR.rlb; if (LL.llb == mid - l + 1)ans.llb += RR.llb; if (LL.llw == mid - l + 1)ans.llw += RR.llw; if (RR.rlb == r - mid)ans.rlb += LL.rlb; if (RR.rlw == r - mid)ans.rlw += LL.rlw; ans.Lw = max(ans.Lw, LL.rlw + RR.llw); ans.Lb = max(ans.Lb, LL.rlb + RR.llb); return ans; } int main() { //ios::sync_with_stdio(0); rdint(n); rdint(m); build(1, n, 1); while (m--) { int op, a, b; rdint(op); rdint(a); rdint(b); a++; b++; if (op == 0)upd1(1, n, 1, a, b); if (op == 1)upd2(1, n, 1, a, b); if (op == 2)upd3(1, n, 1, a, b); if (op == 3)cout << query1(1, n, 1, a, b) << endl; if (op == 4)cout << query2(1, n, 1, a, b).Lw << endl; } return 0; }
EPFL - Fighting