Sequence operation(线段树区间多种操作)

Sequence operation

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

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

题解:测试数据对了但是一直re。。。。先贴着吧。。。

0,1,2,代表操作,0代表将区间内全部变为0,1代表区间内全部变为1,2代表区间内0,1取反

3,4代表查询,3代表查询区间内1的总数,4代表查询区间内最长连续1的个数

re代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<vector>
using namespace std;
const int INF=0x3f3f3f3f;
#define mem(x,y) memset(x,y,sizeof(x))
#define SI(x) scanf("%d",&x)
#define PI(x) printf("%d",x)
#define SD(x,y) scanf("%lf%lf",&x,&y)
#define P_ printf(" ")
#define ll root<<1
#define rr root<<1|1
#define lson ll,l,mid
#define rson rr,mid+1,r
typedef long long LL;
const int MAXN=200010;
struct Node{
    int len,n0,ln0,rn0,sum,v,lazy,x_or;
    int n1,ln1,rn1;
    Node init(){
        SI(v);
        n0=ln0=rn0=(v==0);
        n1=ln1=rn1=(v==1);
        sum=v;
    }
};
Node tree[MAXN<<1];
void XOR(int root,int v){
    swap(tree[root].n0,tree[root].n1);
    swap(tree[root].ln0,tree[root].ln1);
    swap(tree[root].rn0,tree[root].rn1);
    tree[root].sum=v-tree[root].sum;
    if(tree[root].lazy!=-1)tree[root].lazy^=1;
    //printf("%d %d %d %d %d %d\n",tree[root].n0,tree[root].ln0,tree[root].rn0,tree[root].n1,tree[root].ln1,tree[root].rn1);
}
void pushup(int root){
    tree[root].sum=tree[ll].sum+tree[rr].sum;
    tree[root].ln0=tree[ll].ln0;
    tree[root].rn0=tree[rr].rn0;
    if(tree[ll].ln0==tree[ll].len)tree[root].ln0+=tree[rr].ln0;
    if(tree[rr].rn0==tree[rr].len)tree[root].rn0+=tree[ll].rn0;
    tree[root].n0=max(max(tree[root].ln0,tree[root].rn0),tree[ll].rn0+tree[rr].ln0);

    tree[root].ln1=tree[ll].ln1;
    tree[root].rn1=tree[rr].rn1;
    if(tree[ll].ln1==tree[ll].len)tree[root].ln1+=tree[rr].ln1;
    if(tree[rr].rn1==tree[rr].len)tree[root].rn1+=tree[ll].rn1;
    tree[root].n1=max(max(tree[root].ln1,tree[root].rn1),tree[ll].rn1+tree[rr].ln1);

}
void pushdown(int root,int v){
    if(tree[root].lazy!=-1){
        tree[ll].lazy=tree[rr].lazy=tree[root].lazy;
        tree[ll].ln0=tree[ll].n0=tree[ll].rn0=tree[root].lazy?0:tree[ll].len;
        tree[rr].ln0=tree[rr].n0=tree[rr].rn0=tree[root].lazy?0:tree[rr].len;
        tree[rr].ln1=tree[rr].n1=tree[rr].rn1=tree[root].lazy?tree[rr].len:0;
        tree[ll].ln1=tree[ll].n1=tree[ll].rn1=tree[root].lazy?tree[ll].len:0;
        tree[ll].sum=tree[root].lazy?tree[ll].len:0;
        tree[rr].sum=tree[root].lazy?tree[rr].len:0;
        /*
        tree[root].sum=v;
        tree[root].ln0=tree[root].rn0=tree[root].lazy?0:tree[root].len;
        tree[root].ln1=tree[root].rn1=tree[root].lazy?tree[root].len:0;
        */
        tree[ll].x_or=tree[rr].x_or=0;
        tree[root].lazy=-1;
    }
    if(tree[root].x_or){
        tree[ll].x_or^=1;
        tree[rr].x_or^=1;
        XOR(ll,tree[ll].len);
        XOR(rr,tree[rr].len);
        tree[root].x_or=0;
    }
}
void build(int root,int l,int r){
    tree[root].len=r-l+1;
    tree[root].lazy=-1;
    tree[root].x_or=0;
    if(l==r){
        tree[root].init();return;
    }
    int mid=(l+r)>>1;
    build(lson);build(rson);
    pushup(root);
}
void update(int root,int l,int r,int A,int B,int c){
    int mid=(l+r)>>1;
    pushdown(root,tree[root].len);
    if(l>=A&&r<=B){
        //printf("c=%d\n",c);
        if(c<2){
            tree[root].lazy=c;
            tree[root].sum=tree[root].lazy?tree[root].len:0;
        tree[root].n0=tree[root].ln0=tree[root].rn0=tree[root].lazy?0:tree[root].len;
        tree[root].n1=tree[root].ln1=tree[root].rn1=tree[root].lazy?tree[root].len:0;
        }
        else{
             tree[root].x_or=1;
            XOR(root,tree[root].len);
        }
        return;
    }
    pushdown(root,r-l+1);
    if(mid>=A)update(lson,A,B,c);
    if(mid<B)update(rson,A,B,c);
    pushup(root);
}
int query(int root,int l,int r,int A,int B,int c){
    if(l>=A&&r<=B){
    //    printf("%d %d\n",tree[root].sum,tree[root].n1);
        if(c==3)return tree[root].sum;
        else return tree[root].n1;
    }
    pushdown(root,r-l+1);
    int mid=(l+r)>>1;
    if(mid>=B)return query(lson,A,B,c);
    else if(mid<A)return query(rson,A,B,c);
    else{
        int ans1=query(lson,A,mid,c);
        int ans2=query(rson,mid+1,B,c);
        if(c==3)return ans1+ans2;
        else return max(max(ans1,ans2),min(mid-A+1,tree[ll].rn1)+min(B-mid,tree[rr].ln1));
    }
}
int main(){
    int T,N,M;
    SI(T);
    while(T--){
        SI(N);SI(M);
        build(1,0,N-1);
    while(M--){
            int p,a,b;
        scanf("%d%d%d",&p,&a,&b);
        if(p<=2)update(1,0,N-1,a,b,p);
        else{
            printf("%d\n",query(1,0,N-1,a,b,p));
        }
        }
    }
    return 0;
}
时间: 2024-08-01 10:46:40

Sequence operation(线段树区间多种操作)的相关文章

hdu 3397 Sequence operation (线段树 区间合并 多重标记)

链接:http://acm.hdu.edu.cn/showproblem.php?pid=3397 题意: 给你一串01串,有5种操作 0. 区间全部变为0 1.区间全部变为1 2.区间异或 3.询问区间1的个数 4.询问区间被最长连续1的长度 思路: 这5个操作都是比较基础的线段树操作,难点在于有两种修改操作,这类题之前也写过,之前是乘法和加法,这个是区间亦或和区间更新值,但是思路是可以借鉴的,我们要推出这两个操作的关系,这样才能维护好这两个标记,我们用两个标记:same , rev ,分别表

hdu 3397 Sequence operation 线段树 区间更新 区间合并

题意: 5种操作,所有数字都为0或1 0 a b:将[a,b]置0 1 a b:将[a,b]置1 2 a b:[a,b]中的0和1互换 3 a b:查询[a,b]中的1的数量 4 a b:查询[a,b]中的最长连续1串的长度 这题看题目就很裸,综合了区间更新,区间合并 我一开始把更新操作全放一个变量,但是在push_down的时候很麻烦,情况很多,容易漏,后来改成下面的 更新的操作可以分为两类,一个是置值(stv),一个是互换(swp).如果stv!=-1,则更新儿子节点的stv,并将儿子的sw

HDU 3397 Sequence operation 线段树

线段树大杂烩~ 各种操作都有,细心点不难1A #include <iostream> #include <cstring> #include <cstdio> #include <algorithm> using namespace std; #define lson rt<<1,l,mid #define rson rt<<1|1,mid + 1,r const int maxn = 1e5 + 10; int lmax[maxn

线段树区间更新操作及Lazy思想(详解)

此题题意很好懂:  给你N个数,Q个操作,操作有两种,‘Q a b ’是询问a~b这段数的和,‘C a b c’是把a~b这段数都加上c. 需要用到线段树的,update:成段增减,query:区间求和 介绍Lazy思想:lazy-tag思想,记录每一个线段树节点的变化值,当这部分线段的一致性被破坏我们就将这个变化值传递给子区间,大大增加了线段树的效率. 在此通俗的解释我理解的Lazy意思,比如现在需要对[a,b]区间值进行加c操作,那么就从根节点[1,n]开始调用update函数进行操作,如果

HDU 3397 Sequence operation (线段树,成段更新,区间合并)

http://acm.hdu.edu.cn/showproblem.php?pid=3397 Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5801    Accepted Submission(s): 1713 Problem Description lxhgww got a sequence

Hdu 3397 Sequence operation(线段树多操作,Lazy思想,成段更新)

Sequence operation Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 6397    Accepted Submission(s): 1899 Problem Description lxhgww got a sequence contains n characters which are all '0's or '1

hdu-3397 Sequence operation 线段树多种标记

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3397 题目大意: 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的长度 解题思路: 线段树多种标记. 需要处理的东西比较多: 做题的时候发现一个问题: 我的宏定义Max不可以用于函数,尤其是递归函数,这样会使得同一函数重复调用好几遍,递归函数的话更会超时. 1

HDU 4578 Transformation (线段树区间多种更新)

http://acm.hdu.edu.cn/showproblem.php?pid=4578 题目大意:对于一个给定序列,序列内所有数的初始值为0,有4种操作.1:区间(x, y)内的所有数字全部加上C:2:区间(x, y)内所有数字全部乘C; 3:区间(x, y)内的所有数字全部重置为C: 4:输出区间(x, y)内所有数字的P次方的和.由于题目为多实例(至少10组样例),故很耿直的更新到叶子节点明显会TLE:因此需优化.可发现题目所有操作都是对区间进行,因此只需要更新 到区间内数字相同即可.

HDU 4578 线段树区间更新(确定区间操作的优先级)

HDU 4578 线段树区间更新 操作有: 区间所有数add(c) 区间所有数mul(c) 区间所有数set(c) 查询有: 区间所有数的p次方和(p>= 1 && p <= 3) 关键是区间更新的三种操作的优先级的确定清楚set>mul>add 关键是:down和update中对区间的更新操作是一回事,可以写成函数方便编程 //#pragma warning (disable: 4786) //#pragma comment (linker, "/STA