HDU 3397 Sequence Operation

    线段树较复杂题,涵盖了线段树的大部分操作。

    这题节点维护:

    ls:左边最长连续1的长度, rs:右边最长连续1的长度  , ms:整个区间的最长连续1的长度 , sum:区间内1的个数  ,mark:操作懒标记

    将取反操作单独做一个函数来处理。

    具体维护见代码:

 

#include <iostream>

#include <cstdio>

#include <cstring>

#include <cmath>

#include <algorithm>

using namespace std;

#define N 100027



struct node

{

    int ls,rs,ms;

    int sum;

    int mark;

}tree[4*N];



int a[N];

int n,m;



void pushup(int l,int r,int rt)

{

    int mid = (l+r)/2;

    tree[rt].sum = tree[2*rt].sum + tree[2*rt+1].sum;

    tree[rt].ls = tree[2*rt].ls;

    if(tree[rt].ls == mid-l+1)

        tree[rt].ls += tree[2*rt+1].ls;

    tree[rt].rs = tree[2*rt+1].rs;

    if(tree[rt].rs == r-mid)

        tree[rt].rs += tree[2*rt].rs;

    tree[rt].ms = max(max(tree[2*rt].ms,tree[2*rt+1].ms),tree[2*rt].rs+tree[2*rt+1].ls);

}



void pushdown(int l,int r,int rt)

{

    int mid = (l+r)/2;

    if(tree[rt].mark != -1)

    {

        tree[2*rt].mark = tree[2*rt+1].mark = tree[rt].mark;

        tree[2*rt].sum = tree[rt].mark*(mid-l+1);

        tree[2*rt+1].sum = tree[rt].mark*(r-mid);

        tree[2*rt].ms = tree[2*rt].ls = tree[2*rt].rs = tree[2*rt].sum;

        tree[2*rt+1].ms = tree[2*rt+1].ls = tree[2*rt+1].rs = tree[2*rt+1].sum;

        tree[rt].mark = -1;

    }

}



void build(int l,int r,int rt)

{

    if(l == r)

    {

        tree[rt].sum = tree[rt].ms = tree[rt].ls = tree[rt].rs = a[l];

        tree[rt].mark = a[l];

        return;

    }

    tree[rt].mark = -1;

    int mid = (l+r)/2;

    build(l,mid,2*rt);

    build(mid+1,r,2*rt+1);

    pushup(l,r,rt);

}



void update_1(int l,int r,int aa,int bb,int op,int rt)

{

    if(aa<=l && bb>=r)

    {

        if(op == 0)

            tree[rt].ms = tree[rt].ls = tree[rt].rs = tree[rt].sum = 0;

        else

            tree[rt].ms = tree[rt].ls = tree[rt].rs = tree[rt].sum = r-l+1;

        tree[rt].mark = op;

        return;

    }

    pushdown(l,r,rt);

    int mid = (l+r)/2;

    if(aa<=mid)

        update_1(l,mid,aa,bb,op,2*rt);

    if(bb>mid)

        update_1(mid+1,r,aa,bb,op,2*rt+1);

    pushup(l,r,rt);

}



void update_2(int l,int r,int aa,int bb,int rt)

{

    if(aa<=l && bb>=r && tree[rt].mark != -1)

    {

        tree[rt].mark = abs(tree[rt].mark - 1);

        if(tree[rt].mark)

            tree[rt].sum = tree[rt].ms = tree[rt].ls = tree[rt].rs = r-l+1;

        else

            tree[rt].sum = tree[rt].ms = tree[rt].ls = tree[rt].rs = 0;

        return;

    }

    pushdown(l,r,rt);

    int mid =(l+r)/2;

    if(aa<=mid)

        update_2(l,mid,aa,bb,2*rt);

    if(bb>mid)

        update_2(mid+1,r,aa,bb,2*rt+1);

    pushup(l,r,rt);

}



int query_3(int l,int r,int aa,int bb,int rt)

{

    if(aa>r || bb<l)

        return 0;

    if(aa<=l && bb>=r)

        return tree[rt].sum;

    pushdown(l,r,rt);

    int mid = (l+r)/2;

    int res = 0;

    if(aa<=mid)

        res += query_3(l,mid,aa,bb,2*rt);

    if(bb>mid)

        res += query_3(mid+1,r,aa,bb,2*rt+1);

    return res;

}



int query_4(int l,int r,int aa,int bb,int rt)

{

    if(aa<=l && bb>=r)

        return tree[rt].ms;

    pushdown(l,r,rt);

    int mid = (l+r)/2;

    if(bb<=mid)

        return query_4(l,mid,aa,bb,2*rt);

    else if(aa>mid)

        return query_4(mid+1,r,aa,bb,2*rt+1);

    else

    {

        int Lf = query_4(l,mid,aa,bb,2*rt);

        int Rt = query_4(mid+1,r,aa,bb,2*rt+1);

        int tmp = min(tree[2*rt].rs,mid-aa+1) + min(tree[2*rt+1].ls,bb-mid);

        return max(max(Lf,Rt),tmp);

    }

}



int main()

{

    int t,i;

    int aa,bb,op;

    scanf("%d",&t);

    while(t--)

    {

        scanf("%d%d",&n,&m);

        for(i=1;i<=n;i++)

            scanf("%d",&a[i]);

        build(1,n,1);

        for(i=0;i<m;i++)

        {

            scanf("%d%d%d",&op,&aa,&bb);

            aa++;bb++;

            if(op<2)

                update_1(1,n,aa,bb,op,1);

            else if(op == 2)

                update_2(1,n,aa,bb,1);

            else if(op == 3)

                printf("%d\n",query_3(1,n,aa,bb,1));

            else

                printf("%d\n",query_4(1,n,aa,bb,1));

        }

    }

    return 0;

}
View Code

 

你可能感兴趣的:(sequence)