【SCOI2010】维护序列

NOI2017的简化版……

就是维护的时候要想清楚怎么讨论。

#include<bits/stdc++.h>
#define lson (o<<1)
#define rson (o<<1|1)
const int N=100010;
using namespace std;
int n,m;
int a[N];
inline int read(){
    int f=1,x=0;char ch;
    do{ch=getchar();if(ch==‘-‘)f=-1;}while(ch<‘0‘||ch>‘9‘);
    do{x=x*10+ch-‘0‘;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘);
    return f*x;
}
struct Segment_Tree{
    int sumv[N<<2],rev[N<<2],setv[N<<2],maxl[N<<2][2],maxr[N<<2][2],maxv[N<<2][2];
    inline void pushup(int o,int l,int r){
        int mid=(l+r)>>1;
        maxl[o][0]=maxl[lson][0];
        if(maxl[lson][0]==mid-l+1)maxl[o][0]+=maxl[rson][0];
        maxr[o][1]=maxr[rson][1];
        if(maxr[rson][1]==r-mid)maxr[o][1]+=maxr[lson][1];
        maxl[o][1]=maxl[lson][1];
        if(maxl[lson][1]==mid-l+1)maxl[o][1]+=maxl[rson][1];
        maxr[o][0]=maxr[rson][0];
        if(maxr[rson][0]==r-mid)maxr[o][0]+=maxr[lson][0];
        maxv[o][1]=max(maxv[lson][1],max(maxv[rson][1],maxr[lson][1]+maxl[rson][1]));
        maxv[o][0]=max(maxv[lson][0],max(maxv[rson][0],maxr[lson][0]+maxl[rson][0]));
        sumv[o]=sumv[lson]+sumv[rson];
    }
    inline void pushdown(int o,int l,int r){
        int mid=(l+r)>>1;
        if(setv[o]!=-1){
            int tag=setv[o];setv[lson]=setv[rson]=setv[o];
            sumv[lson]=tag*(mid-l+1);sumv[rson]=tag*(r-mid);
            maxv[lson][tag]=maxl[lson][tag]=maxr[lson][tag]=mid-l+1;
            maxv[rson][tag]=maxl[rson][tag]=maxr[rson][tag]=r-mid;
            maxv[lson][tag^1]=maxl[lson][tag^1]=maxr[lson][tag^1]=0;
            maxv[rson][tag^1]=maxl[rson][tag^1]=maxr[rson][tag^1]=0;
            setv[o]=-1;rev[o]=0;
        }
        if(rev[o]){
            int lx=0,rx=lx^1;
            rev[lson]^=1;rev[rson]^=1;
            swap(maxv[lson][lx],maxv[lson][rx]);swap(maxv[rson][lx],maxv[rson][rx]);
            swap(maxl[lson][lx],maxl[lson][rx]);swap(maxl[rson][lx],maxl[rson][rx]);
            swap(maxr[lson][lx],maxr[lson][rx]);swap(maxr[rson][lx],maxr[rson][rx]);
            sumv[lson]=mid-l+1-sumv[lson];sumv[rson]=r-mid-sumv[rson];
            if(setv[lson]!=-1)setv[lson]^=1;
            if(setv[rson]!=-1)setv[rson]^=1;
            rev[o]=0;
        }
    }
    inline void build(int o,int l,int r){
        rev[o]=0;setv[o]=-1;
        if(l==r){
            sumv[o]=a[l];int lx=a[l],rx=lx^1;
            maxv[o][lx]=maxl[o][lx]=maxr[o][lx]=1;
            maxv[o][rx]=maxl[o][rx]=maxr[o][rx]=0;
            return;
        }
        int mid=(l+r)>>1;
        build(lson,l,mid);build(rson,mid+1,r);
        pushup(o,l,r);
    }
    inline void sett(int o,int l,int r,int ql,int qr,int v){
        if(ql<=l&&r<=qr){int rx=v^1;
            sumv[o]=(r-l+1)*v;setv[o]=v;maxv[o][v]=maxl[o][v]=maxr[o][v]=r-l+1;
            rev[o]=0;maxv[o][rx]=maxl[o][rx]=maxr[o][rx]=0;
            return;
        }
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(ql<=mid)sett(lson,l,mid,ql,qr,v);
        if(qr>mid)sett(rson,mid+1,r,ql,qr,v);
        pushup(o,l,r);
    }
    inline void rever(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr){
            rev[o]^=1;swap(maxv[o][0],maxv[o][1]);swap(maxl[o][0],maxl[o][1]);swap(maxr[o][0],maxr[o][1]);
            sumv[o]=(r-l+1)-sumv[o];
            if(setv[o]!=-1)setv[o]^=1;
            return;
        }
        int mid=(l+r)>>1;pushdown(o,l,r);
        if(ql<=mid)rever(lson,l,mid,ql,qr);
        if(qr>mid)rever(rson,mid+1,r,ql,qr);
        pushup(o,l,r);
    }
    inline int querysum(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return sumv[o];
        int mid=(l+r)>>1,ans=0;
        pushdown(o,l,r);
        if(ql<=mid)ans+=querysum(lson,l,mid,ql,qr);
        if(qr>mid)ans+=querysum(rson,mid+1,r,ql,qr);
        return ans;
    }
    inline int querymax(int o,int l,int r,int ql,int qr){
        if(ql<=l&&r<=qr)return maxv[o][1];
        int mid=(l+r)>>1;int ans=0;
        pushdown(o,l,r);
        if(ql<=mid)ans=max(ans,querymax(lson,l,mid,ql,qr));
        if(qr>mid)ans=max(ans,querymax(rson,mid+1,r,ql,qr));
        if(ql<=mid&&qr>mid)ans=max(ans,min(mid-ql+1,maxr[lson][1])+min(qr-mid,maxl[rson][1]));
        return ans;
    }
}T;
int main(){
    n=read();m=read();
    for(int i=1;i<=n;i++)a[i]=read();
    T.build(1,1,n);
    while(m--){
        int opt=read(),l=read(),r=read();
        l++;r++;
        if(opt==0)T.sett(1,1,n,l,r,0);
        if(opt==1)T.sett(1,1,n,l,r,1);
        if(opt==2)T.rever(1,1,n,l,r);
        if(opt==3)printf("%d\n",T.querysum(1,1,n,l,r));
        if(opt==4)printf("%d\n",T.querymax(1,1,n,l,r));
    }
}
时间: 2024-10-29 03:50:28

【SCOI2010】维护序列的相关文章

1798: [Ahoi2009]Seq 维护序列seq

1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 5886  Solved: 2087[Submit][Status][Discuss] Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和

bzoj1798[Ahoi2009]Seq 维护序列seq

bzoj1798[Ahoi2009]Seq 维护序列seq 题意: 维护序列,支持区间加.区间乘.区间求和模一个数.序列大小和操作数≤100000 题解: 线段树,加标记和乘标记的处理同bzoj4003.模的时候注意细节. 代码: 1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #define inc(i,j,k) for(int i=j;i<=k;i++) 5 #define m

bzoj1798: [Ahoi2009]Seq 维护序列seq 2011-12-20

1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MB Submit: 497  Solved: 203 [Submit][Status][Discuss] Description 老 师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的

BZOJ1798题解 Seq维护序列题解 双tag裸线段树

BZOJ1798题解 Seq维护序列题解 双tag裸线段树 1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec  Memory Limit: 64 MBSubmit: 5549  Solved: 1951[Submit][Status][Discuss] Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)

bzoj 1798: [Ahoi2009]Seq 维护序列seq 线段树 区间乘法区间加法 区间求和

1798: [Ahoi2009]Seq 维护序列seq Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/problem.php?id=1798 Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列

洛谷 P2023 [AHOI2009]维护序列

P2023 [AHOI2009]维护序列 题目描述 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,…,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值. 输入输出格式 输入格式: 第一行两个整数N和P(1≤P≤1000000000). 第二行含有N个非负整数,从左到右依次为a1,a2,…,aN, (0≤ai≤100

bzoj1798: [Ahoi2009]Seq 维护序列seq(线段树多重标记下传)

www.cnblogs.com/shaokele/ bzoj1798: [Ahoi2009]Seq 维护序列seq Time Limit: 30 Sec Memory Limit: 64 MB Description 老师交给小可可一个维护数列的任务,现在小可可希望你来帮他完成. 有长为N的数列,不妨设为a1,a2,-,aN .有如下三种操作形式: (1)把数列中的一段数全部乘一个值; (2)把数列中的一段数全部加一个值; (3)询问数列中的一段数的和,由于答案可能很大,你只需输出这个数模P的值

P2023 [AHOI2009]维护序列 题解(线段树

题目链接 P2023 [AHOI2009]维护序列 解题思路 线段树板子.不难,但是...有坑.坑有多深?一页\(WA\). 由于乘法可能乘\(k=0\),我这种做法可能会使结果产生负数.于是就有了这篇题解. (详情见代码注释) AC代码 #include<stdio.h> #define min(a,b) (a>b?b:a) #define max(a,b) (a>b?a:b) typedef long long ll; int n,m; ll mod,k,a[500010];

BZOJ 1798 AHOI2009 Seq 维护序列 线段树

题目大意:维护一个序列,提供三种操作: 1.将区间中每个点的权值乘上一个数 2.将区间中每个点的权值加上一个数 3.求一段区间的和对p取模的值 2631的超^n级弱化版.写2631之前能够拿这个练练手... 线段树区间改动,让学校的大神指导了一下ZKW的区间改动方法,非常好理解,可是代码还是快不了. . . 回头再改改代码吧 可能是我写的太渣了 #include<cstdio> #include<cstring> #include<iostream> #include&