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
",query_3(1,n,aa,bb,1));
            else
                printf("%d
",query_4(1,n,aa,bb,1));
        }
    }
    return 0;
}
View Code
原文地址:https://www.cnblogs.com/whatbeg/p/3539399.html