线段树 HDU 3397 Sequence operation

来源:互联网 发布:广告词制作软件 编辑:程序博客网 时间:2024/05/17 01:47

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

代码风格:http://www.notonlysuccess.com/index.php/segment-tree-complete/


题目大意:操作说明:0——把[a,b]区间全部变成0;1——把[a, b]区间全部变成1;2——把[a,b]区间0,1取反;3——输出[a,b]区间1的个数;4——输出[a, b]区间最长连续1的长度

算法:线段树 区间合并

思路:0,1 操作如果不会可以去做一下POJ3367,代码见http://www.notonlysuccess.com/index.php/segment-tree-complete/

同时统计0和1的左边连续个数lsun,lsum,右边连续个数rsun,rsum,区间最长连续个数msun,msum以及区间内1的个数p

0,1操作时,把取反标记清零

2操作:建立数组x[]作为取反标记,并且lsum,rsun互换,rsum,rsun互换,msum, msun互换,p改变

#include"cstdio"#include"cstring"#include"cmath"#include"algorithm"using namespace std;const int Max = 444444;#define lson l, m, rt << 1#define rson m+1, r, rt << 1 | 1#define mid int m  = (l+r) >> 1int lsun[Max], rsun[Max], msun[Max];int rsum[Max], lsum[Max], msum[Max];int cover[Max], p[Max], x[Max];void fxor(int rt){    if(cover[rt] != -1)        cover[rt] ^= 1;    else x[rt] ^= 1;}int max(int a, int b){    return a > b ? a : b;}int min(int a, int b){    return a < b ? a : b;}void PushUp(int l, int r, int rt, int m){    //printf("%d -- %d, rt == %d\n", p[rt << 1 ], p[rt << 1 | 1], rt);    p[rt] = p[rt << 1 ] + p[rt << 1 | 1];    rsum[rt] = rsum[rt << 1 | 1];    rsun[rt] = rsun[rt << 1 | 1];    lsum[rt] = lsum[rt << 1];    lsun[rt] = lsun[rt << 1];    if(lsun[rt] == m - (m >> 1))        lsun[rt] += lsun[rt << 1 | 1];    if(lsum[rt] == m - (m >> 1))        lsum[rt] += lsum[rt << 1 | 1];    if(rsun[rt] == m >> 1)        rsun[rt] += rsun[rt << 1];    if(rsum[rt] == m >> 1)        rsum[rt] += rsum[rt << 1];    msum[rt] = max(max(msum[rt << 1], msum[rt << 1 | 1]), lsum[rt << 1 | 1] + rsum[rt << 1]);    msun[rt] = max(max(msun[rt << 1], msun[rt << 1 | 1]), lsun[rt << 1 | 1] + rsun[rt << 1 ]);}void PushDown(int rt, int m){    if(cover[rt] != -1)    {        cover[rt << 1] = cover[rt << 1 | 1] = cover[rt];        msum[rt << 1] = rsum[rt << 1] = lsum[rt << 1] = p[rt << 1] = cover[rt] * (m - (m >> 1));        msum[rt << 1 | 1] = rsum[rt << 1 | 1] = lsum[rt << 1 | 1] = p[rt << 1 | 1] = cover[rt] * (m >> 1);        msun[rt << 1] = rsun[rt << 1] = lsun[rt << 1] = cover[rt] ? 0 : m - (m >> 1);        msun[rt << 1 | 1] = rsun[rt << 1 | 1] = lsun[rt << 1 | 1] = cover[rt] ?0 : m >> 1;        x[rt << 1] = x[rt << 1 | 1] = 0;        cover[rt] = -1;    }    if(x[rt] != 0)    {        fxor(rt << 1);        fxor(rt << 1 | 1);        p[rt << 1] = (m - (m >> 1)) - p[rt << 1];        p[rt << 1 | 1] = (m >> 1) - p[rt << 1 | 1];        int k = lsum[rt << 1]; lsum[rt << 1] = lsun[rt << 1]; lsun[rt << 1] = k;        k = rsum[rt << 1]; rsum[rt << 1] = rsun[rt << 1]; rsun[rt << 1] = k;        k = msum[rt << 1]; msum[rt << 1] = msun[rt << 1]; msun[rt << 1] = k;        k = lsum[rt << 1 | 1]; lsum[rt << 1 | 1] = lsun[rt << 1 | 1]; lsun[rt << 1 | 1] = k;        k = rsum[rt << 1 | 1]; rsum[rt << 1 | 1] = rsun[rt << 1 | 1]; rsun[rt << 1 | 1] = k;        k = msum[rt << 1 | 1]; msum[rt << 1 | 1] = msun[rt << 1 | 1]; msun[rt << 1 | 1] = k;        x[rt] = 0;    }}void build(int l, int r, int rt){    if(l == r)    {        scanf("%d", &p[rt]);        rsum[rt] = msum[rt] = lsum[rt] = p[rt] ? 1 : 0;        rsun[rt] = msun[rt] = lsun[rt] = p[rt] ? 0 : 1;        //printf("msum[rt] = %d\n", msum[rt]);        return ;    }    mid ;    build(lson);    build(rson);    PushUp(m, m+1, rt, r-l+1);}void update(int op, int L, int R, int l, int r, int rt){    if(L <= l && r <= R)    {        if(op == 2)        {            p[rt] = r-l+1-p[rt];            int k = lsum[rt]; lsum[rt] = lsun[rt]; lsun[rt] = k;            k = rsum[rt]; rsum[rt] = rsun[rt]; rsun[rt] = k;            k = msum[rt]; msum[rt] = msun[rt]; msun[rt] = k;            fxor(rt);        }        else        {            cover[rt] = op;            lsum[rt] = msum[rt] = rsum[rt] = p[rt] = op ? r-l+1 : 0;            lsun[rt] = msun[rt] = rsun[rt] = op ? 0 : r-l+1;            x[rt] = 0;        }        return ;    }    mid ;    PushDown(rt, r-l+1);    if(L <= m)        update(op, L, R, lson);    if(m < R)        update(op, L, R, rson);    PushUp(m, m+1, rt, r-l+1);}int query(int L, int R, int l, int r, int rt){    if(L <= l && r <= R)    {        return p[rt];    }    int ret = 0;    PushDown(rt, r-l+1);    mid;    if(L <= m)        ret += query(L, R, lson);    if(m < R)        ret += query(L, R, rson);    return ret ;}int Query(int L, int R, int l, int r, int rt){    if(L <= l && r <= R)    {        return msum[rt];    }    mid;    PushDown(rt, r-l+1);    if(m < L)        return Query(L, R, rson);    else if(R <= m)        return Query(L, R, lson);    return max(max(min(rsum[rt << 1], m+1-L) + min(lsum[rt << 1 | 1], R-m), Query(L, R, lson)), Query(L, R, rson) );}int main(){    int T, n, m;    scanf("%d", &T);    while( T --)    {        memset(x, 0, sizeof(x));        memset(cover, -1, sizeof(cover));        scanf("%d%d", &n, &m);        build(0, n-1, 1);        while(m --)        {            int a, b, c;            scanf("%d%d%d", &a, &b, &c);            if(a < 3)                update(a, b, c, 0, n-1, 1);            else if(a == 3)                printf("%d\n", query(b, c, 0, n-1, 1));            else printf("%d\n", Query(b, c, 0, n-1, 1));        }    }    return 0;}


原创粉丝点击