码迷,mamicode.com
首页 > 其他好文 > 详细

hdu 3397 Sequence operation(线段树:区间更新)

时间:2015-11-02 11:42:47      阅读:215      评论:0      收藏:0      [点我收藏+]

标签:

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 

题意:给你一个长度为n的0,1序列,支持下列五种操作,

操作0(0 a b):将a到b这个区间的元素全部置为0。

操作1(1 a b):将a到b这个区间的元素全部置为1。

操作2(2 a b):将a到b这个区间所有的0置为1,所有的1置为0。

操作3(3 a b):查询a到b这个区间1的总数。

操作4(4 a b):查询a到b这个区间连续1的最长长度

本题属于简单的区间更新线段树

重点:0操作和1操作都属于普通的set操作,可以直接覆盖其他操作,但是2操作需要仔细考虑。操作2在其他的操作之后不能直接采用覆盖的方式,比如(1 left right) (2 left right)的操作序列,如果直接覆盖就变成了(2 left right),而实际上应该变成(0 left right)。大家可以看下代码中的deal_xor函数。

感想:主啊,眼睛都快敲瞎了,敲完还一直wrong,瞬间??。

#include <iostream>
#include <cstring>
#include <algorithm>
#define maxn 400010
#define inf 1000000000
#define LL(x) x<<1
#define RR(x) x<<1|1
using namespace std;

typedef long long LL;

//variable define

struct tree
{
    int l, r;
    int cnt;
    int lsum0, rsum0, sum0;
    int lsum1, rsum1, sum1;
    int set;
};

tree node[maxn];
int n, m;

//function define

void push_down(int x);

void push_up(int x);

void build_tree(int left, int right, int x);

tree query(int left, int right, int x);

void update_set(int left, int right, int x, int val);

int deal_xor(int x)
{
    if (node[x].set == -1)
        return 2;
    else if (node[x].set == 0)
        return 1;
    else if (node[x].set == 1)
        return 0;
    else
        return -1;
}

int main(void)
{
    int ncase;
    scanf("%d", &ncase);
    while (ncase--)
    {
        scanf("%d %d", &n, &m);
        build_tree( 1, n, 1);
        int op, x, y;
        while (m--)
        {
            scanf("%d %d %d", &op, &x, &y);
            x += 1;
            y += 1;
            if (op == 0)
            {
                update_set( x, y, 1, op);
            }
            else if (op == 1)
            {
                update_set( x, y, 1, op);
            }
            else if (op == 2)
            {
                update_set( x, y, 1, op);
            }
            else if (op == 3)
            {
                tree result = query( x, y, 1);
                printf("%d\n", result.cnt);
            }
            else
            {
                tree result = query( x, y, 1);
                printf("%d\n", result.sum1);
            }
        }
    }
    return 0;
}

void build_tree(int left, int right, int x)
{
    node[x].l = left;
    node[x].r = right;
    node[x].set = -1;
    if (left == right)
    {
        int t;
        scanf("%d", &t);
        if (t == 1)
        {
            node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 1;
            node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 0;
            
        }
        else
        {
            node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 0;
            node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 1;
        }
        return;
    }
    
    int lx = LL(x);
    int rx = RR(x);
    int mid = left + (right - left)/2;
    build_tree(left, mid, lx);
    build_tree(mid + 1, right, rx);
    push_up(x);
}

void push_up(int x)
{
    if (node[x].l >= node[x].r)
        return;
    
    int lx = LL(x);
    int rx = RR(x);
    node[x].cnt = node[lx].cnt + node[rx].cnt;
    node[x].sum1 = max( node[lx].rsum1 + node[rx].lsum1, max( node[lx].sum1, node[rx].sum1));
    node[x].lsum1 = node[lx].lsum1 == (node[lx].r - node[lx].l + 1) ? node[lx].lsum1 + node[rx].lsum1 : node[lx].lsum1;
    node[x].rsum1 = node[rx].rsum1 == (node[rx].r - node[rx].l + 1) ? node[rx].rsum1 + node[lx].rsum1 : node[rx].rsum1;
    node[x].sum0 = max( node[lx].rsum0 + node[rx].lsum0, max( node[lx].sum0, node[rx].sum0));
    node[x].lsum0 = node[lx].lsum0 == (node[lx].r - node[lx].l + 1) ? node[lx].lsum0 + node[rx].lsum0 : node[lx].lsum0;
    node[x].rsum0 = node[rx].rsum0 == (node[rx].r - node[rx].l + 1) ? node[rx].rsum0 + node[lx].rsum0 : node[rx].rsum0;
}

void push_down(int x)
{
    if (node[x].l >= node[x].r)
        return;
    int lx = LL(x);
    int rx = RR(x);
    if (node[x].set != -1)
    {
        if (node[x].set == 0)
        {
            node[lx].cnt = node[lx].sum1 = node[lx].lsum1 = node[lx].rsum1 = 0;
            node[lx].sum0 = node[lx].lsum0 = node[lx].rsum0 = node[lx].r - node[lx].l + 1;
            node[rx].cnt = node[rx].sum1 = node[rx].lsum1 = node[rx].rsum1 = 0;
            node[rx].sum0 = node[rx].lsum0 = node[rx].rsum0 = node[rx].r - node[rx].l + 1;
            node[lx].set = node[rx].set = 0;
        }
        else if (node[x].set == 1)
        {
            node[lx].cnt = node[lx].sum1 = node[lx].lsum1 = node[lx].rsum1 = node[lx].r - node[lx].l + 1;
            node[lx].sum0 = node[lx].lsum0 = node[lx].rsum0 = 0;
            node[rx].cnt = node[rx].sum1 = node[rx].lsum1 = node[rx].rsum1 = node[rx].r - node[rx].l + 1;
            node[rx].sum0 = node[rx].lsum0 = node[rx].rsum0 = 0;
            node[lx].set = node[rx].set = 1;
        }
        else
        {
            int t1, t2, t3;
            node[lx].set = deal_xor(lx);
            node[lx].cnt = node[lx].r - node[lx].l + 1 - node[lx].cnt;
            t1 = node[lx].sum1;
            t2 = node[lx].lsum1;
            t3 = node[lx].rsum1;
            node[lx].sum1 = node[lx].sum0;
            node[lx].lsum1 = node[lx].lsum0;
            node[lx].rsum1 = node[lx].rsum0;
            node[lx].sum0 = t1;
            node[lx].lsum0 = t2;
            node[lx].rsum0 = t3;
            
            node[rx].set = deal_xor(rx);
            node[rx].cnt = node[rx].r - node[rx].l + 1 - node[rx].cnt;
            t1 = node[rx].sum1;
            t2 = node[rx].lsum1;
            t3 = node[rx].rsum1;
            node[rx].sum1 = node[rx].sum0;
            node[rx].lsum1 = node[rx].lsum0;
            node[rx].rsum1 = node[rx].rsum0;
            node[rx].sum0 = t1;
            node[rx].lsum0 = t2;
            node[rx].rsum0 = t3;
        }
    }
}

void update_set(int left, int right, int x, int val)
{
    if (node[x].l == left && node[x].r == right)
    {
        if (val == 0)
        {
            node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = 0;
            node[x].sum0 = node[x].lsum0 = node[x].rsum0 = node[x].r - node[x].l + 1;
            node[x].set = 0;
        }
        else if (val == 1)
        {
            node[x].cnt = node[x].sum1 = node[x].lsum1 = node[x].rsum1 = node[x].r - node[x].l + 1;
            node[x].sum0 = node[x].lsum0 = node[x].rsum0 = 0;
            node[x].set = 1;
        }
        else
        {
            node[x].set = deal_xor(x);
            node[x].cnt = node[x].r - node[x].l + 1 - node[x].cnt;
            int t1, t2, t3;
            t1 = node[x].sum1;
            t2 = node[x].lsum1;
            t3 = node[x].rsum1;
            node[x].sum1 = node[x].sum0;
            node[x].lsum1 = node[x].lsum0;
            node[x].rsum1 = node[x].rsum0;
            node[x].sum0 = t1;
            node[x].lsum0 = t2;
            node[x].rsum0 = t3;
        }
        return;
    }
    push_down(x);
    node[x].set = -1;
    int lx = LL(x);
    int rx = RR(x);
    int mid = node[x].l + (node[x].r - node[x].l)/2;
    if (right <= mid)
        update_set(left, right, lx, val);
    else if (left > mid)
        update_set(left, right, rx, val);
    else
    {
        update_set(left, mid, lx, val);
        update_set(mid + 1, right, rx, val);
    }
    push_up( x);
}

tree query(int left, int right, int x)
{
    if (node[x].l == left && node[x].r == right)
    {
        return node[x];
    }
    push_down(x);
    node[x].set = -1;
    int mid = node[x].l + (node[x].r - node[x].l)/2;
    int lx = LL(x);
    int rx = RR(x);
    tree ans;
    if (right <= mid)
        ans = query(left, right, lx);
    else if (left > mid)
        ans = query(left, right, rx);
    else
    {
        tree lnode = query(left, mid, lx);
        tree rnode = query(mid + 1, right, rx);
        ans.cnt = lnode.cnt + rnode.cnt;
        ans.sum1 = max( lnode.rsum1 + rnode.lsum1, max( lnode.sum1, rnode.sum1));
        ans.lsum1 = lnode.lsum1 == (lnode.r - lnode.l + 1) ? lnode.lsum1 + rnode.lsum1 : lnode.lsum1;
        ans.rsum1 = rnode.rsum1 == (rnode.r - rnode.l + 1) ? rnode.rsum1 + lnode.rsum1 : rnode.rsum1;
        ans.sum0 = max( lnode.rsum0 + rnode.lsum0, max( lnode.sum0, rnode.sum0));
        ans.lsum0 = lnode.lsum0 == (lnode.r - lnode.l + 1) ? lnode.lsum0 + rnode.lsum0 : lnode.lsum0;
        ans.rsum0 = rnode.rsum0 == (rnode.r - rnode.l + 1) ? rnode.rsum0 + lnode.rsum0 : rnode.rsum0;
    }
    push_up(x);
    return ans;
}

 

hdu 3397 Sequence operation(线段树:区间更新)

标签:

原文地址:http://www.cnblogs.com/chuninsane/p/4929535.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!