HDU 3397 Sequence operation (线段树)
2013-04-10 09:06
435 查看
题目:http://acm.hdu.edu.cn/showproblem.php?pid=3397
题意:。。。。。。
分析:线段树。难点是怎样处理好3个标记变量(fg0置0;fg1置1;fg2取反)相互之间的关系!其实,fg0和fg1基本是一样的,可以合二为一(fg01)。这样就变成了fg01与fg22(fg2)的关系的处理。
一个例子:先把[a,b]置0(或置1),再把[a,b]取反,此时,置0(或置1)以及取反都是有效的,必须把两者都保存下来并且进行处理。
另一个例子:先把[a,b]取反,再把[a,b]置0(或置1),此时,相当于没有取反,而只有置0(或置1),此时应当把取反操作屏蔽掉(否则会出错)。
通过上面两个简单的例子,我们可以看出(至少可以这么认为):置0(或置1)操作的优先权大于取反操作的优先权!
把这个问题解决掉,这个题就差不多了吧,,,
一组简单的数据:
1
7 8
1 1 1 1 0 1 0
0 2 6
1 4 5
2 1 4
0 3 4
2 2 3
0 0 5
4 3 4
3 2 2
答案:
0
0
题意:。。。。。。
分析:线段树。难点是怎样处理好3个标记变量(fg0置0;fg1置1;fg2取反)相互之间的关系!其实,fg0和fg1基本是一样的,可以合二为一(fg01)。这样就变成了fg01与fg22(fg2)的关系的处理。
一个例子:先把[a,b]置0(或置1),再把[a,b]取反,此时,置0(或置1)以及取反都是有效的,必须把两者都保存下来并且进行处理。
另一个例子:先把[a,b]取反,再把[a,b]置0(或置1),此时,相当于没有取反,而只有置0(或置1),此时应当把取反操作屏蔽掉(否则会出错)。
通过上面两个简单的例子,我们可以看出(至少可以这么认为):置0(或置1)操作的优先权大于取反操作的优先权!
把这个问题解决掉,这个题就差不多了吧,,,
一组简单的数据:
1
7 8
1 1 1 1 0 1 0
0 2 6
1 4 5
2 1 4
0 3 4
2 2 3
0 0 5
4 3 4
3 2 2
答案:
0
0
#include<cstdio> #include<algorithm> using namespace std; const int maxn=5+200000; int n,m; struct TREE { int fg01; bool fg22; int sum; int M11[3]; int M00[3]; }T[maxn*4]; inline int L(int &x) {return x<<1; } inline int R(int &x) {return x<<1|1; } #define leson L(root),le,mid #define rison R(root),mid+1,ri void f_maintain(int root,int len) { int a=L(root), b=R(root), lena=(len+1)>>1, lenb=len>>1; T[root].sum = T[a].sum+T[b].sum; T[root].M11[0] = T[a].M11[0]; if(T[root].M11[0] == lena) T[root].M11[0] += T[b].M11[0]; T[root].M11[1] = T[b].M11[1]; if(T[root].M11[1] == lenb) T[root].M11[1] += T[a].M11[1]; T[root].M11[2] = max(T[a].M11[2], T[b].M11[2]); T[root].M11[2] = max(T[root].M11[2], T[a].M11[1]+T[b].M11[0]); T[root].M00[0] = T[a].M00[0]; if(T[root].M00[0] == lena) T[root].M00[0] += T[b].M00[0]; T[root].M00[1] = T[b].M00[1]; if(T[root].M00[1] == lenb) T[root].M00[1] += T[a].M00[1]; T[root].M00[2] = max(T[a].M00[2], T[b].M00[2]); T[root].M00[2] = max(T[root].M00[2], T[a].M00[1]+T[b].M00[0]); } void f_build(int root,int le,int ri) { T[root].fg01 = -1; T[root].fg22 = false; if(le == ri) { scanf("%d", &T[root].sum); T[root].M11[0] = T[root].M11[1] = T[root].M11[2] = T[root].sum; T[root].M00[0] = T[root].M00[1] = T[root].M00[2] = 1-T[root].sum; return ; } int mid=(le+ri)>>1; f_build(leson); f_build(rison); f_maintain(root, ri-le+1); } void f_giveson(int t, int son,int len) { T[son].fg01 = t; T[son].fg22 = false; ///********notice here*********/// T[son].sum = len*t; T[son].M11[0] = T[son].M11[1] = T[son].M11[2] = len*t; T[son].M00[0] = T[son].M00[1] = T[son].M00[2] = len*(t^1); } void f_sonXOR(int son,int len) { T[son].fg22 ^= 1; T[son].sum = len-T[son].sum; swap(T[son].M11[0], T[son].M00[0]); swap(T[son].M11[1], T[son].M00[1]); swap(T[son].M11[2], T[son].M00[2]); } void f_pushdown(int root,int len) { if(len == 1) return ; int a=L(root), b=R(root), lena=(len+1)>>1, lenb=len>>1; if(T[root].fg01 != -1) { f_giveson(T[root].fg01, a, lena); f_giveson(T[root].fg01, b, lenb); T[root].fg01 = -1; } if(T[root].fg22) { f_sonXOR(a,lena); f_sonXOR(b,lenb); T[root].fg22 = false; } } int Mle,Mri; void f_update(int root,int le,int ri,int t) { f_pushdown(root, ri-le+1); if(Mle <= le && ri <= Mri) { if(t == 2) f_sonXOR(root, ri-le+1); else f_giveson(t, root, ri-le+1); return ; } int mid=(le+ri)>>1; if(Mle <= mid) f_update(leson,t); if(Mri > mid) f_update(rison,t); f_maintain(root, ri-le+1); } int Qle,Qri; int f_query_on(int root,int le,int ri) { f_pushdown(root, ri-le+1); if(Qle <= le && ri <= Qri) return T[root].sum; int mid=(le+ri)>>1, ans=0; if(Qle <= mid) ans += f_query_on(leson); if(Qri > mid) ans += f_query_on(rison); return ans; } int f_query_conti(int root,int le,int ri) { f_pushdown(root, ri-le+1); if(Qle <= le && ri <= Qri) return T[root].M11[2]; int mid=(le+ri)>>1; if(Qri <= mid) return f_query_conti(leson); else if(Qle > mid) return f_query_conti(rison); else { int ansle=f_query_conti(leson); int ansri=f_query_conti(rison); int ans=min(ansle, T[L(root)].M11[1])+min(ansri, T[R(root)].M11[0]); return max(ans, max(ansle,ansri)); } } int main() { int test,t,a,b; scanf("%d", &test); while(test--) { scanf("%d %d", &n,&m); f_build(1, 1,n); while(m--) { scanf("%d %d %d", &t,&a,&b); a++,b++; if(a > b) swap(a,b); Mle=Qle=a, Mri=Qri=b; if(t <= 2) f_update(1,1,n,t); if(t == 3) printf("%d\n", f_query_on(1,1,n)); if(t == 4) printf("%d\n", f_query_conti(1,1,n)); } } return 0; }
相关文章推荐
- 【线段树】HDU 3397 Sequence operation 区间合并
- HDU 3397 线段树区间染色 区间查询
- hdu 3397 Sequence operation 线段树 区间更新 区间合并
- HDU 3397 线段树 较麻烦
- HDU 3397 - Sequence operation(线段树+区间合并)
- HDU 3397 Sequence operation(线段树:成段更新,查询连续目标子串长度)
- hdu 3397 线段树前后缀blahblah Sequence operation
- HDU-3397 线段树+区间合并
- hdu 3397 线段树
- HDU 3397——Sequence operation(线段树,区间染色+区间异或+区间合并)
- HDU 3397 Sequence operation(线段树)
- HDU 3397(线段树,较难~)
- HDU 3397 Sequence operation (线段树)
- HDU 3397 Sequence operation 线段树
- HDU 3397 Sequence operation(线段树区间更行)
- HDU 3397 Sequence operation(线段树区间合并+区间修改)
- HDU 3397 Sequence operation 线段树综合题
- Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)
- HDU 3397 Sequence operation(线段树)
- hdu 3397 Sequence operation(线段树的各种操作)