HDU 3397 Sequence operation (线段树)

题目: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;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值