HDU3397 Sequence operation(线段树的区间合并)

来源:互联网 发布:微控加群软件 编辑:程序博客网 时间:2024/05/23 16:13

Sequence operation

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 7547    Accepted Submission(s): 2254


Problem Description
lxhgww got a sequence contains n characters which are all '0's or '1's.
We have five operations here:
Change operations:
0 a b change all characters into '0's in [a , b]
1 a b change all characters into '1's in [a , b]
2 a b change all '0's into '1's and change all '1's into '0's in [a, b]
Output operations:
3 a b output the number of '1's in [a, b]
4 a b output the length of the longest continuous '1' string in [a , b]
 

Input
T(T<=10) in the first line is the case number.
Each case has two integers in the first line: n and m (1 <= n , m <= 100000).
The next line contains n characters, '0' or '1' separated by spaces.
Then m lines are the operations:
op a b: 0 <= op <= 4 , 0 <= a <= b < n.
 

Output
For each output operation , output the result.
 

Sample Input
110 100 0 0 1 1 0 1 0 1 11 0 23 0 52 2 24 0 40 3 62 3 74 2 81 0 50 5 63 3 9
 

Sample Output
5265
 

Author
lxhgww&&shǎ崽
 

Source
HDOJ Monthly Contest – 2010.05.01
 

Recommend
lcy   |   We have carefully selected several similar problems for you:  1698 1540 2871 1255 3333 
题意:
0 a b 把[a,b]内的数都改成0
1 a b 把[a,b]内的数都改成1
2 a b [a,b]内1改为0,0改为1

3 a b 输出[a,b]内1的个数
4 a b 输出[a,b]内1的连续序列最长长度。

思路:
对于0和1的个数统计应该不难,线段树的基本操作,求区间和。
对于区间合并
举例数字1,处理区间内1的最长连续序列长度。
每个区间应该记录包含左端点最长连续序列长度lmax, 包含右端点最长连续序列长度rmax, 整个区间的最长连续序列长度max。
向上更新的时候,一个区间的lmax等于它左儿子的lmax,如果lmax刚好等于左儿子的整个区间,就加上右儿子的lmax,;
同理这个区间的rmax等于它右儿子的rmax,如果rmax刚好等于右儿子的整个区间,就要加上左儿子的rmax。
一个区间的max等于左儿子max, 右儿子max,还有中间那部分(左儿子rmax+右儿子的lmax)三者间最大的值。
这样就可以处理区间内最长的连续序列长度。

updata的时候要整段更新,由于向下更新可能会出现多个标记叠在一起未被处理,也就是修改同一个区间多次后又访问它的儿子区间。
0操作后进行1操作其实相当进行1操作,1操作后进行2操作相当于进行0操作,类似地可以用一个数组表示操作之间的转换,使得标记一直都只是一种操作,这样向下更新可以一次处理。

#include <stdio.h>#include <string.h>#include <algorithm>#define lson rt<<1#define rson rt<<1|1#define maxn 200010using namespace std;struct node{    int left, right;    int num0, num1, zmx, omx;    int zlx, zrx, olx, orx;    int dis(){return right-left+1;}}t[maxn<<2];int par[3][3];int add[maxn<<2];void pushUp(int rt){    t[rt].zlx = t[lson].zlx + (t[lson].zlx==t[lson].dis()?t[rson].zlx:0);    t[rt].zrx = t[rson].zrx + (t[rson].zrx==t[rson].dis()?t[lson].zrx:0);    t[rt].olx = t[lson].olx + (t[lson].olx==t[lson].dis()?t[rson].olx:0);    t[rt].orx = t[rson].orx + (t[rson].orx==t[rson].dis()?t[lson].orx:0);    t[rt].num0 = t[lson].num0 + t[rson].num0;    t[rt].num1 = t[lson].num1 + t[rson].num1;    t[rt].zmx = max(max(t[lson].zmx, t[rson].zmx), t[lson].zrx+t[rson].zlx);    t[rt].omx = max(max(t[lson].omx, t[rson].omx), t[lson].orx+t[rson].olx);}int x;void build(int rt, int l, int r){    t[rt].left = l;    t[rt].right = r;    add[rt] = -1;    if(l == r){        scanf("%d", &x);        if(x == 0){            t[rt].num0 = t[rt].zmx = t[rt].zlx = t[rt].zrx = 1;            t[rt].num1 = t[rt].omx = t[rt].olx = t[rt].orx = 0;        }else{            t[rt].num0 = t[rt].zmx = t[rt].zlx = t[rt].zrx = 0;            t[rt].num1 = t[rt].omx = t[rt].olx = t[rt].orx = 1;        }        return;    }    int mid = (l+r)>>1;    build(lson, l, mid);    build(rson, mid+1, r);    pushUp(rt);}void change0(int rt){    t[rt].num0 = t[rt].zmx = t[rt].zlx = t[rt].zrx = t[rt].dis();    t[rt].num1 = t[rt].omx = t[rt].olx = t[rt].orx = 0;}void change1(int rt){    t[rt].num0 = t[rt].zmx = t[rt].zlx = t[rt].zrx = 0;    t[rt].num1 = t[rt].omx = t[rt].olx = t[rt].orx = t[rt].dis();}void change2(int rt){    swap(t[rt].num0, t[rt].num1);    swap(t[rt].zmx, t[rt].omx);    swap(t[rt].zlx, t[rt].olx);    swap(t[rt].zrx, t[rt].orx);}void Par(int fa, int son){    if(add[son] == -1) add[son] = add[fa];    else add[son] = par[add[son]][add[fa]];}void pushDown(int rt){    if(add[rt] != -1){        Par(rt, lson);        Par(rt, rson);        if(add[rt] == 0){            change0(lson);            change0(rson);        }else if(add[rt] == 1){            change1(lson);            change1(rson);        }else if(add[rt] == 2){            change2(lson);            change2(rson);        }        add[rt] = -1;    }}void updata(int rt, int l, int r, int op){    pushDown(rt);    if(l==t[rt].left&&t[rt].right==r){        if(add[rt] == -1) add[rt] = op;        else add[rt] = par[add[rt]][op];        if(add[rt] == 0) change0(rt);        else if(add[rt] == 1) change1(rt);        else if(add[rt] == 2) change2(rt);        return;    }    int mid = (t[rt].left+t[rt].right)>>1;    if(r<=mid) updata(lson, l, r, op);    else if(mid<l) updata(rson, l, r, op);    else{        updata(lson, l, mid, op);        updata(rson, mid+1, r, op);    }    pushUp(rt);}int query(int rt, int l, int r, int ask){    pushDown(rt);    if(l==t[rt].left&&t[rt].right==r){        if(ask == 3) return t[rt].num1;        else return t[rt].omx;    }    int mid = (t[rt].left+t[rt].right)>>1;    if(r<=mid) return query(lson, l, r, ask);    else if(l>mid) return query(rson, l, r, ask);    else{        int ltmp = query(lson, l, mid, ask);        int rtmp = query(rson, mid+1, r, ask);        int sum = 0;        sum = min(t[lson].orx, mid-l+1) + min(t[rson].olx, r-mid);        if(ask == 4) return max(max(ltmp, rtmp), sum);//求1连续        else return (ltmp+rtmp);//求1个数    }}int main(){    int T, i, n, m, op, c, d;    par[0][0] = 0, par[0][1] = 1, par[0][2] = 1;    par[2][2] = -1, par[2][0] = 0, par[2][1] = 1;    par[1][1] = 1, par[1][0] = 0, par[1][2] = 0;    scanf("%d", &T);    while(T--){        scanf("%d %d", &n, &m);        build(1, 1, n);        while(m--){            scanf("%d %d %d", &op, &c, &d);            if(op<3) updata(1, c+1, d+1, op);            else printf("%d\n", query(1, c+1, d+1, op));        }    }}/*110 100 0 0 1 0 1 0 1 1 11 0 92 0 92 0 54 0 9*/

0 0
原创粉丝点击