您的位置:首页 > 产品设计 > UI/UE

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

#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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: