HDU3397(Sequence operation)线段树解法

                                       Sequence operation

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


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

题意:首先给出一组数据:由0和1组成,然后有5种操作。

0 a b表示把[a,b]区间的数全部变成0;

1 a b 表示把[a,b]区间的数全部变成1;

2 a b表示把[a,b]区间的0变成1、1变成0,也就是进行异或操作;

3 a b就是问你[a,b]区间总共有多少个1,;

4 a b就是问你[a,b]区间最长的连续的1的个数。

思路:就是线段树区间求和,区间更新,区间合并,区间修改,懒惰结点。思路上没什么难的,但是细节真的巨多,巨多啊。可能因为我代码功力弱的原因,调到绝望。

下面总结一下我被卡的重要细节:

1,查询区间中1的最多连续个数时要考虑三种情况,左区间最长,右区间区间最长和左区间右端连续1长度+右区间左端点连续长度进行三者比较。

2,左区间左端点连续长度在左区间全是1的情况下等于左区间长度+右区间左端点连续长度。右区间右端点连续长度同理。

3,懒惰结点下放时当前懒惰结点是区间0边1,1变0时,要考虑其左右孩子的懒惰结点被标记的是什么。

      (1)如果其孩子的懒惰结点没被标记,那么直接标记下放。

      (2)如果其孩子懒惰结点是全变1,那么将其变成全变0。

      (3)如果其孩子懒惰结点是全变0,那么将其变成全变1。

      (4)如果其孩子懒惰结点是0变1,1变0,那么将其变为未标记状态。

可以仔细考虑第三条,因为2号操作的懒惰结点的下放会影响到孩子的懒惰结点,所以要进行判断。

#include <set>
#include <map>
#include <deque>
#include <stack>
#include <queue>
#include <time.h>
#include <vector>
#include <string>
#include <math.h>
#include <cstring>
#include <cstdlib>
#include <stdio.h>
#include <iomanip>
#include <iostream>
#include <algorithm>
#define PI acos(-1)
#define ll long long
#define LL long long
#define inf 0x3f3f3f3f
#define ull unsigned long long
using namespace std;
const int maxn=100005;
struct node
{
    int l,r;
    int sum;
    int add;

    int len1_max;
    int l1_max;
    int r1_max;

    int len0_max;
    int l0_max;
    int r0_max;
}tree[maxn*6];

void pushdown(int i)
{
    if(tree[i].add==1)//全变成1
    {
        tree[i].add=0;

        tree[i*2].add=1;
        tree[i*2].sum=tree[i*2].r-tree[i*2].l+1;

        tree[i*2+1].add=1;
        tree[i*2+1].sum=tree[i*2+1].r-tree[i*2+1].l+1;

        tree[i*2].len0_max=0;
        tree[i*2].l0_max=0;
        tree[i*2].r0_max=0;

        tree[i*2].len1_max=tree[i*2].r-tree[i*2].l+1;
        tree[i*2].l1_max=tree[i*2].r-tree[i*2].l+1;
        tree[i*2].r1_max=tree[i*2].r-tree[i*2].l+1;

        tree[i*2+1].len0_max=0;
        tree[i*2+1].l0_max=0;
        tree[i*2+1].r0_max=0;

        tree[i*2+1].len1_max=tree[i*2+1].r-tree[i*2+1].l+1;
        tree[i*2+1].l1_max=tree[i*2+1].r-tree[i*2+1].l+1;
        tree[i*2+1].r1_max=tree[i*2+1].r-tree[i*2+1].l+1;
    }
    else if(tree[i].add==2)//全变成0
    {
        tree[i].add=0;

        tree[i*2].add=2;
        tree[i*2].sum=0;

        tree[i*2+1].add=2;
        tree[i*2+1].sum=0;

        tree[i*2].len0_max=tree[i*2].r-tree[i*2].l+1;
        tree[i*2].l0_max=tree[i*2].r-tree[i*2].l+1;
        tree[i*2].r0_max=tree[i*2].r-tree[i*2].l+1;

        tree[i*2].len1_max=0;
        tree[i*2].l1_max=0;
        tree[i*2].r1_max=0;

        tree[i*2+1].len0_max=tree[i*2+1].r-tree[i*2+1].l+1;
        tree[i*2+1].l0_max=tree[i*2+1].r-tree[i*2+1].l+1;
        tree[i*2+1].r0_max=tree[i*2+1].r-tree[i*2+1].l+1;

        tree[i*2+1].len1_max=0;
        tree[i*2+1].l1_max=0;
        tree[i*2+1].r1_max=0;
    }
    else if(tree[i].add==3)//将所有数取逆
    {
        tree[i].add=0;

        //tree[i*2].add=3;
        if(tree[i*2].add==1) tree[i*2].add=2;
        else if(tree[i*2].add==2) tree[i*2].add=1;
        else if(tree[i*2].add==3) tree[i*2].add=0;
        else if(tree[i*2].add==0) tree[i*2].add=3;
        tree[i*2].sum=tree[i*2].r-tree[i*2].l+1-tree[i*2].sum;

        //tree[i*2+1].add=3;
        if(tree[i*2+1].add==1) tree[i*2+1].add=2;
        else if(tree[i*2+1].add==2) tree[i*2+1].add=1;
        else if(tree[i*2+1].add==3) tree[i*2+1].add=0;
        else if(tree[i*2+1].add==0) tree[i*2+1].add=3;
        tree[i*2+1].sum=tree[i*2+1].r-tree[i*2+1].l+1-tree[i*2+1].sum;

        swap(tree[i*2].len0_max,tree[i*2].len1_max);
        swap(tree[i*2].l0_max,tree[i*2].l1_max);
        swap(tree[i*2].r0_max,tree[i*2].r1_max);

        swap(tree[i*2+1].len0_max,tree[i*2+1].len1_max);
        swap(tree[i*2+1].l0_max,tree[i*2+1].l1_max);
        swap(tree[i*2+1].r0_max,tree[i*2+1].r1_max);
    }
}
void pushup(int i)
{
    tree[i].sum=tree[i*2].sum+tree[i*2+1].sum;

    tree[i].len1_max=max(tree[i*2].len1_max,tree[i*2+1].len1_max);
    tree[i].len1_max=max(tree[i].len1_max,tree[i*2].r1_max+tree[i*2+1].l1_max);

    if(tree[i*2].len1_max==tree[i*2].r-tree[i*2].l+1) tree[i].l1_max=tree[i*2].l1_max+tree[i*2+1].l1_max;
    else tree[i].l1_max=tree[i*2].l1_max;
    if(tree[i*2+1].len1_max==tree[i*2+1].r-tree[i*2+1].l+1) tree[i].r1_max=tree[i*2+1].r1_max+tree[i*2].r1_max;
    else tree[i].r1_max=tree[i*2+1].r1_max;

    tree[i].len0_max=max(tree[i*2].len0_max,tree[i*2+1].len0_max);
    tree[i].len0_max=max(tree[i].len0_max,tree[i*2].r0_max+tree[i*2+1].l0_max);

    if(tree[i*2].len0_max==tree[i*2].r-tree[i*2].l+1) tree[i].l0_max=tree[i*2].l0_max+tree[i*2+1].l0_max;
    else tree[i].l0_max=tree[i*2].l0_max;
    if(tree[i*2+1].len0_max==tree[i*2+1].r-tree[i*2+1].l+1) tree[i].r0_max=tree[i*2+1].r0_max+tree[i*2].r0_max;
    else tree[i].r0_max=tree[i*2+1].r0_max;
}
void build(int i,int l,int r)
{
    tree[i].l=l;
    tree[i].r=r;
    tree[i].add=0;
    if(l==r)
    {
        scanf("%d",&tree[i].sum);
        if(tree[i].sum==1)
        {
            tree[i].len0_max=0;
            tree[i].l0_max=0;
            tree[i].r0_max=0;
            tree[i].len1_max=1;
            tree[i].l1_max=1;
            tree[i].r1_max=1;
        }
        else
        {
            tree[i].len0_max=1;
            tree[i].l0_max=1;
            tree[i].r0_max=1;
            tree[i].len1_max=0;
            tree[i].l1_max=0;
            tree[i].r1_max=0;
        }
        return ;
    }
    int mid=(l+r)>>1;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
    pushup(i);
}
void update(int L,int R,int val,int i)
{
    pushdown(i);
    if(L<=tree[i].l&&tree[i].r<=R)
    {
        if(val==1)//全变成1
        {
            tree[i].sum=tree[i].r-tree[i].l+1;
            tree[i].add=1;

            tree[i].len1_max=tree[i].r-tree[i].l+1;
            tree[i].l1_max=tree[i].r-tree[i].l+1;
            tree[i].r1_max=tree[i].r-tree[i].l+1;

            tree[i].len0_max=0;
            tree[i].l0_max=0;
            tree[i].r0_max=0;
        }
        else if(val==2)//全变成0
        {
            tree[i].sum=0;
            tree[i].add=2;

            tree[i].len0_max=tree[i].r-tree[i].l+1;
            tree[i].l0_max=tree[i].r-tree[i].l+1;
            tree[i].r0_max=tree[i].r-tree[i].l+1;

            tree[i].len1_max=0;
            tree[i].l1_max=0;
            tree[i].r1_max=0;
        }
        else if(val==3)//全取反
        {
            tree[i].sum=tree[i].r-tree[i].l+1-tree[i].sum;
            tree[i].add=3;

            swap(tree[i].len0_max,tree[i].len1_max);
            swap(tree[i].l0_max,tree[i].l1_max);
            swap(tree[i].r0_max,tree[i].r1_max);
        }
        return ;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    if(mid>=L) update(L,R,val,i*2);
    if(mid<R) update(L,R,val,i*2+1);
    pushup(i);
}
int query(int L,int R,int i)
{
    pushdown(i);
    if(L<=tree[i].l&&tree[i].r<=R)
    {
        return tree[i].sum;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    int ans=0;
    if(L<=mid) ans+=query(L,R,i*2);
    if(mid<R) ans+=query(L,R,i*2+1);
    return ans;
}
int query_len(int L,int R,int i)
{
    pushdown(i);
    if(L<=tree[i].l&&tree[i].r<=R)
    {
        return tree[i].len1_max;
    }
    int mid=(tree[i].l+tree[i].r)>>1;
    int ans=0;
    if(R <= mid)return query_len(L,R,i*2);
    else if(L > mid)return query_len(L,R,i*2+1);
    else
    {
        int ans1 = 0,ans2 = 0;
        ans1 = query_len(L,mid,i*2);
        ans2 = query_len(mid+1,R,i*2+1);
        ans = min(tree[i<<1].r1_max,mid-L+1)+min(tree[i<<1|1].l1_max,R-mid);
        return max(ans,max(ans1,ans2));
    }
    return ans;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,q,op,a,b;
        scanf("%d%d",&n,&q);
        memset(tree,0,sizeof(tree));
        build(1,1,n);
        while(q--)
        {
            scanf("%d%d%d",&op,&a,&b);
            a++;
            b++;
            if(op==0)//全变成0
            {
                update(a,b,2,1);
            }
            else if(op==1)//全变成1
            {
                update(a,b,1,1);
            }
            else if(op==2)//0变1,1变0
            {
                update(a,b,3,1);
            }
            else if(op==3)//区间求和
            {
                cout<<query(a,b,1)<<endl;
            }
            else if(op==4)//区间最长连续1
            {
                cout<<query_len(a,b,1)<<endl;
            }
        }
    }
}

 

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值