hdu3397Sequence operation(线段树区间合并)

来源:互联网 发布:知乎用户开放注册 编辑:程序博客网 时间:2024/06/07 20:16

题目链接:hdu3397

线段树区间合并,和poj3667类似,都是老套路。。。

#include <iostream>#include <queue>#include <cstdio>#include <cstring>#include <algorithm>using namespace std;#define lson l, m, rt<<1#define rson m+1, r, rt<<1|1const int N = 200005;struct node{    int col;    int llen,rlen,mlen;    int num;//区间内1的数量}s[N<<2];void pushup(int rt, int m)//更新父节点{    s[rt].llen = s[rt<<1].llen;    s[rt].rlen = s[rt<<1|1].rlen;    if(s[rt].llen == m-(m>>1)) s[rt].llen += s[rt<<1|1].llen;    if(s[rt].rlen == (m>>1)) s[rt].rlen += s[rt<<1].rlen;    s[rt].mlen = max(s[rt<<1].rlen + s[rt<<1|1].llen, max(s[rt<<1].mlen, s[rt<<1|1].mlen) );    s[rt].num = s[rt<<1].num + s[rt<<1|1].num;//左儿子和右儿子的num和}void pushdown(int rt, int m)//更新子节点{    if(s[rt].col == 1)    {        s[rt<<1].num = m - (m>>1);        s[rt<<1|1].num = (m>>1);    }    if(s[rt].col == 0)        s[rt<<1].num = s[rt<<1|1].num = 0;    if(s[rt].col != -1)    {        s[rt<<1].llen = s[rt<<1].rlen = s[rt<<1].mlen = (s[rt].col==1?m-(m>>1):0);        s[rt<<1|1].llen = s[rt<<1|1].rlen = s[rt<<1|1].mlen = (s[rt].col==1?(m>>1):0);        s[rt<<1].col = s[rt<<1|1].col = s[rt].col;        s[rt].col = -1;    }}void build(int l, int r, int rt){    s[rt].col = -1;    if(l == r)    {        scanf("%d",&s[rt].col);        if(s[rt].col == 1)        {            s[rt].llen = s[rt].rlen = s[rt].mlen = 1;            s[rt].num = 1;        }        else s[rt].llen = s[rt].rlen = s[rt].mlen = s[rt].num = 0;        return;    }    int m = (l+r) >> 1;    build(lson);    build(rson);    pushup(rt, r-l+1);}void change(int l, int r, int rt)//进行操作2,即将区间内的0变为1,1变为0{    if(s[rt].col == 0)//将0变为1    {        s[rt].col = 1;        s[rt].num = s[rt].llen = s[rt].rlen = s[rt].mlen =  r-l+1;        return;    }    if(s[rt].col == 1)//将1变为0    {        s[rt].col = 0;        s[rt].num = s[rt].llen = s[rt].rlen = s[rt].mlen = 0;        return;    }    if(l == r) return;    int m = (l+r) >> 1;    change(lson);    change(rson);    pushup(rt, r-l+1);}void update(int c, int L, int R, int l, int r, int rt){    if(L <= l && r <= R)    {        if(c == 0)//操作0,将区间内所有数变为0        {            s[rt].col = 0;            s[rt].num = 0;            s[rt].llen = s[rt].rlen = s[rt].mlen = 0;        }        else if(c == 1)//操作1,将区间内所有数变为1        {            s[rt].col = 1;            s[rt].num = r-l+1;            s[rt].llen = s[rt].rlen = s[rt].mlen = r-l+1;        }        else if(c == 2) change(l, r, rt);        return ;    }    pushdown(rt, r-l+1);    int m = (l+r) >> 1;    if(L <= m) update(c, L, R, lson);    if(R > m) update(c, L, R, rson);    pushup(rt, r-l+1);}int query3(int L, int R, int l, int r, int rt)//操作3,查1的个数{    if(L <= l && r <= R)        return s[rt].num;    pushdown(rt, r-l+1);    int m = (l+r) >> 1;    int ans = 0;    if(L <= m) ans += query3(L, R, lson);    if(m < R) ans += query3(L, R, rson);    return ans;}int query4(int L, int R, int l, int r, int rt)//操作4,查连续个1的长度{    if(L <= l && r <= R)        return s[rt].mlen;    pushdown(rt, r-l+1);    int m = (l+r) >> 1;    int ans = 0;    if(L <= m)        ans = max(ans, query4(L, R, lson));    if(m < R)        ans = max(ans, query4(L, R, rson));    ans = max(ans, min(m-L+1,s[rt<<1].rlen) + min(R-m, s[rt<<1|1].llen) );//很重要    return ans;}int main(){    //freopen("in.txt","r",stdin);    int T,n,m;    scanf("%d",&T);    while(T--)    {        scanf("%d%d",&n,&m);        build(1, n, 1);        int x,y,z;        while(m--)        {            scanf("%d%d%d",&x,&y,&z);            if(x < 3) update(x, y+1, z+1, 1, n, 1);            if(x == 3) printf("%d\n",query3(y+1, z+1, 1, n, 1));            if(x == 4) printf("%d\n",query4(y+1, z+1, 1, n, 1));        }    }    return 0;}


0 0
原创粉丝点击