JZOJ 4933. 【NOIP2017提高组模拟12.24】C

来源:互联网 发布:三菱fx3gaplc编程软件 编辑:程序博客网 时间:2024/05/08 23:04

Description

Description

Input

Input

Sample Input

10 9
3580 8597 508 9110 9162 9973 6017 1942 989 646
1 3 4 405
4 3 5
5 6 7
6 4 9
7 5 7
2 1 8 9623
5 1 6
4 2 7
3 7 7 8581

Output

Output

Sample Output

19590
6017
9973
1
-8710
-13561

Data Constraint

Solution

  • 超级码农题!!!

  • 显然线段树,第①②④⑤⑥问都可以轻易处理出来

  • 对于第③问,只需维护一下标志数组,也不难处理

  • 而本题的关键是第⑦问!

  • 对于一个区间,记录以下一些量:

    1.最左边的数
    2.最右边的数
    3.以最左边为起点往右延伸个数
    4.以最右边为起点往左延伸个数
    5.答案(最长子串)

  • 这样合并方法就很显然了!

  • 为处理方便也可记录区间元素个数,时间复杂度 O(Nlogn)

Code

#include<cstdio>#include<algorithm>using namespace std;const int N=100001,MX=1e9;typedef long long LL;struct data{    int max,min,left,right,lnum,rnum,len,cnt;    LL sum;}f[8*N];int n,q,num,sum;int a[N],c[8*N],d[8*N];LL ans;inline int read(){    int data=0; char ch=0;    while(ch<'0' || ch>'9') ch=getchar();    while(ch>='0' && ch<='9') data=data*10+ch-'0',ch=getchar();    return data;}inline void updata(int v){    int ls=2*v,rs=ls+1;    f[v].max=max(f[ls].max,f[rs].max);    f[v].min=min(f[ls].min,f[rs].min);    f[v].sum=f[ls].sum+f[rs].sum;    f[v].lnum=f[ls].lnum,f[v].rnum=f[rs].rnum;    f[v].left=f[ls].left,f[v].right=f[rs].right;    f[v].len=max(f[ls].len,f[rs].len);    if(f[ls].rnum==f[rs].lnum)    {        f[v].len=max(f[v].len,f[ls].right+f[rs].left);        if(f[ls].left==f[ls].cnt) f[v].left+=f[rs].left;        if(f[rs].right==f[rs].cnt) f[v].right+=f[ls].right;    }}inline void modify(int v){    int ls=v*2,rs=v*2+1;    if(d[v]==1)    {        f[v].max+=c[v],f[v].min+=c[v];        f[v].lnum+=c[v],f[v].rnum+=c[v];        f[v].sum+=f[v].cnt*c[v];        c[ls]+=c[v],c[rs]+=c[v];        if(!d[ls]) d[ls]=1;        if(!d[rs]) d[rs]=1;        c[v]=d[v]=0;    }else    if(d[v]==2)    {        f[v].max=f[v].min=f[v].lnum=f[v].rnum=c[v];        f[v].sum=f[v].cnt*c[v];        f[v].len=f[v].left=f[v].right=f[v].cnt;        c[ls]=c[rs]=c[v];        d[ls]=d[rs]=2;        c[v]=d[v]=0;    }}inline void make(int v,int l,int r){    if(l==r)    {        f[v].sum=f[v].max=f[v].min=f[v].lnum=f[v].rnum=a[l];        f[v].len=f[v].left=f[v].right=f[v].cnt=1;        return;    }    int mid=(l+r)>>1,ls=2*v,rs=ls+1;    make(ls,l,mid),make(rs,mid+1,r);    f[v].cnt=f[ls].cnt+f[rs].cnt;    updata(v);}inline void find(int v,int l,int r,int x,int y,int pd){    if(l==x && r==y)    {        if(pd==4) ans+=f[v].sum; else            if(pd==5) ans=min(ans,(LL)f[v].min); else ans=max(ans,(LL)f[v].max);        return;    }    int mid=(l+r)>>1,ls=2*v,rs=ls+1;    modify(ls),modify(rs);    if(y<=mid) find(ls,l,mid,x,y,pd); else        if(x>mid) find(rs,mid+1,r,x,y,pd); else        {            find(ls,l,mid,x,mid,pd);            find(rs,mid+1,r,mid+1,y,pd);        }}inline int find_all(int v,int l,int r,int x,int y){    if(l==x && r==y) return f[v].len;    int mid=(l+r)>>1,ls=2*v,rs=ls+1;    modify(ls),modify(rs);    if(y<=mid) return find_all(ls,l,mid,x,y); else        if(x>mid) return find_all(rs,mid+1,r,x,y); else        {            int sum=max(find_all(ls,l,mid,x,mid),find_all(rs,mid+1,r,mid+1,y));            if(f[ls].rnum==f[rs].lnum) sum=max(sum,min(f[ls].right,mid-x+1)+min(f[rs].left,y-mid));            return sum;        }}inline void change(int v,int l,int r,int x,int y,int z){    if(l==x && r==y)    {        c[v]=z,d[v]=1;        modify(v);        return;    }    int mid=(l+r)>>1,ls=2*v,rs=ls+1;    modify(ls),modify(rs);    if(y<=mid) change(ls,l,mid,x,y,z); else        if(x>mid) change(rs,mid+1,r,x,y,z); else        {            change(ls,l,mid,x,mid,z);            change(rs,mid+1,r,mid+1,y,z);        }    updata(v);}inline void change_all(int v,int l,int r,int x,int y,int z){    if(l==x && r==y)    {        c[v]=z,d[v]=2;        modify(v);        return;    }    int mid=(l+r)>>1,ls=2*v,rs=ls+1;    modify(ls),modify(rs);    if(y<=mid) change_all(ls,l,mid,x,y,z); else        if(x>mid) change_all(rs,mid+1,r,x,y,z); else        {            change_all(ls,l,mid,x,mid,z);            change_all(rs,mid+1,r,mid+1,y,z);        }    updata(v);}int main(){    n=read(),q=read();    for(int i=1;i<=n;i++) a[i]=read();    make(1,1,n);    while(q--)    {        int t=read(),l=read(),r=read();        if(t==7) printf("%d\n",find_all(1,1,n,l,r)); else        if(t<=3)        {            int v=read();            if(t==3) change_all(1,1,n,l,r,v); else            {                if(t==2) v=-v;                change(1,1,n,l,r,v);            }        }else        {            if(t==4) ans=0; else                if(t==5) ans=MX; else ans=-MX;            find(1,1,n,l,r,t);            printf("%lld\n",ans);        }    }    return 0;}
1 0