hdu 3397 Sequence operation(线段树的各种操作)

Sequence operation

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


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
  
  
1 10 10 0 0 0 1 1 0 1 0 1 1 1 0 2 3 0 5 2 2 2 4 0 4 0 3 6 2 3 7 4 2 8 1 0 5 0 5 6 3 3 9
 

Sample Output
  
  
5 2 6 5
 

Author
lxhgww&&shǎ崽
 

Source
 

Recommend
lcy
 

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

题意:给你一个01字符串,对一段区间可能的操作有置0,置1,翻转,询问1的个数,询问最多有多少个连续的1。。。

分析:这题其实就是把各种操作合在一道题上面了,所以代码长一些而已,难度还是一样的。。。就不解释了,不懂的见前面几道题,或者看看代码啥的

代码:

#include<cstdio>
#include<iostream>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int mm=111111;
int dly[mm<<2],rev[mm<<2],sum[mm<<2];
int mla[mm<<2],mlb[mm<<2],lma[mm<<2],lmb[mm<<2],rma[mm<<2],rmb[mm<<2];
void set(int rt,int op,int len)
{
    sum[rt]=(op-1)*len;
    mla[rt]=lma[rt]=rma[rt]=(op-1)*len;
    mlb[rt]=lmb[rt]=rmb[rt]=(2-op)*len;
    dly[rt]=op,rev[rt]=0;
}
void reverse(int rt,int len)
{
    sum[rt]=len-sum[rt];
    swap(mla[rt],mlb[rt]);
    swap(lma[rt],lmb[rt]);
    swap(rma[rt],rmb[rt]);
    rev[rt]^=1;
}
void pushdown(int rt,int l1,int l2)
{
    if(rev[rt])
    {
        if(dly[rt])dly[rt]=3-dly[rt];
        else reverse(rt<<1,l1),reverse(rt<<1|1,l2);
        rev[rt]=0;
    }
    if(dly[rt])
    {
        set(rt<<1,dly[rt],l1),set(rt<<1|1,dly[rt],l2);
        dly[rt]=0;
    }
}
void pushup(int rt,int l1,int l2)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    mla[rt]=max(rma[rt<<1]+lma[rt<<1|1],max(mla[rt<<1],mla[rt<<1|1]));
    mlb[rt]=max(rmb[rt<<1]+lmb[rt<<1|1],max(mlb[rt<<1],mlb[rt<<1|1]));
    lma[rt]=lma[rt<<1],rma[rt]=rma[rt<<1|1];
    lmb[rt]=lmb[rt<<1],rmb[rt]=rmb[rt<<1|1];
    if(lma[rt]>=l1)lma[rt]+=lma[rt<<1|1];
    if(lmb[rt]>=l1)lmb[rt]+=lmb[rt<<1|1];
    if(rma[rt]>=l2)rma[rt]+=rma[rt<<1];
    if(rmb[rt]>=l2)rmb[rt]+=rmb[rt<<1];
}
void build(int l,int r,int rt)
{
    dly[rt]=rev[rt]=0;
    if(l==r)
    {
        scanf("%d",&sum[rt]);
        mla[rt]=lma[rt]=rma[rt]=sum[rt];
        mlb[rt]=lmb[rt]=rmb[rt]=!sum[rt];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt,m-l+1,r-m);
}
void updata(int L,int R,int op,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        if(op)set(rt,op,r-l+1);
        else reverse(rt,r-l+1);
        return;
    }
    int m=(l+r)>>1;
    pushdown(rt,m-l+1,r-m);
    if(L<=m)updata(L,R,op,lson);
    if(R>m)updata(L,R,op,rson);
    pushup(rt,m-l+1,r-m);
}
int query(int L,int R,int op,int l,int r,int rt)
{
    if(L<=l&&R>=r)return op?sum[rt]:mla[rt];
    int m=(l+r)>>1,ret=0;
    pushdown(rt,m-l+1,r-m);
    if(op)
    {
        if(L<=m)ret+=query(L,R,op,lson);
        if(R>m)ret+=query(L,R,op,rson);
    }
    else
    {
        if(R<=m)ret=query(L,R,op,lson);
        else if(L>m)ret=query(L,R,op,rson);
        else ret=max(min(R,m+lma[rt<<1|1])-max(L,m-rma[rt<<1]+1)+1,
                     max(query(L,R,op,lson),query(L,R,op,rson)));
    }
    pushup(rt,m-l+1,r-m);
    return ret;
}
int main()
{
    int i,a,b,n,m,t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        build(0,n-1,1);
        while(m--)
        {
            scanf("%d%d%d",&i,&a,&b);
            if(i<3)updata(a,b,(i+1)%3,0,n-1,1);
            else printf("%d\n",query(a,b,4-i,0,n-1,1));
        }
    }
    return 0;
}
date: 2013-11-5
#include <iostream>
#include <cstdio>
using namespace std;
#define REP(i,n) for(int i=0;i<n;i++)
#define N 100010
struct node
{
    node *ls, *rs;
    int num[2], sz;
    int change, turn;
    int ms[2], lms[2], rms[2];
    node(){}
    node(node a, node b)
    {
        ls = &a, rs = &b;
        up();
    }
    void changeIt(int c)
    {
        change = c;
        ms[c] = lms[c] = rms[c] = num[c] = sz;
        c^=1;
        ms[c] = lms[c] = rms[c] = num[c] = 0;
        turn = 0;//赋值后记得清空翻转标记
    }
    void turnIt()
    {
        turn ^=1;
        swap(num[0],num[1]);
        swap(ms[0],ms[1]);
        swap(lms[0],lms[1]);
        swap(rms[0],rms[1]);
    }
    void up()
    {
        REP(i,2)
        {
            num[i] = ls->num[i] + rs->num[i];
            ms[i] = max( ls->rms[i]+rs->lms[i],max(ls->ms[i], rs->ms[i]));
            lms[i] = ls->lms[i];
            rms[i] = rs->rms[i];
            if(lms[i]>=ls->sz)lms[i]+=rs->lms[i];
            if(rms[i]>=rs->sz)rms[i]+=ls->rms[i];
        }
    }
    void down()
    {
        if(change>=0)
        {
            ls->changeIt(change);
            rs->changeIt(change);
            change = -1;
        }
        if(turn)
        {
            ls->turnIt();
            rs->turnIt();
            turn = 0;
        }
    }
};
node mem[N<<2], *root, *cur;
node *new_node()
{
    cur->change = -1;
    cur->turn = 0;
    cur->sz = 1;
    return cur++;
}
void init()
{
    cur = mem;
}
void build(int l, int r, node *&rt)
{
    rt = new_node();
    if(l+1>=r)
    {
        scanf("%d",&rt->change);
        rt->changeIt(rt->change);
        return ;
    }
    int m =(l+r)>>1;
    build(l,m,rt->ls);
    build(m,r,rt->rs);
    rt->sz = rt->ls->sz + rt->rs->sz;
    rt->up();
}
void update(int a, int b, int op, int l, int r, node *rt)
{
    if(a<=l && b+1>=r)
    {
        if(op<2)rt->changeIt(op);
        else rt->turnIt();
        return ;
    }
    int m =(l+r)>>1;
    rt->down();
    if(a<m )update(a,b,op,l,m,rt->ls);
    if(b>=m)update(a,b,op,m,r,rt->rs);
    rt->up();
}
node query(int a, int b, int l, int r, node *rt)
{
    if(a<=l && b+1>=r)return *rt;
    int m = (l+r)>>1;
    rt->down();
    node ret;
    if(b<m ) ret = query(a,b,l,m,rt->ls);
    else if(a>=m) ret = query(a,b,m,r,rt->rs);
    else ret = node( query(a,b,l,m,rt->ls),query(a,b,m,r,rt->rs));
    rt->up();
    return ret;
}
int main(int argc, char ** argv)
{
    int t, n, m, op, a, b;
    scanf("%d", &t);
    while (t--)
    {
        scanf("%d%d",&n,&m);
        init();
        build(0,n,root);
        while (m--)
        {
            scanf("%d%d%d", &op, &a, &b);
            if(op<3)update(a,b,op,0,n,root);
            else
            {
                node now = query(a,b,0,n,root);
                if(op==3)printf("%d\n",now.num[1]);
                else printf("%d\n",now.ms[1]);
            }
        }
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值