uoj169:元旦老人与数列

题意:http://uoj.ac/problem/169

sol  :线段树..........蜜汁TLE了一个点,不管了.....

   代码抄snowMyDream的,orz...........

   线段树需要维护以下奇奇怪怪的一堆东西......

     区间最小值及其lazy标记

     区间严格次小值及其lazy标记

     最小值、严格次小值lazy标记的前缀和,历史最小值

   dalao的博客说了一堆势能之类的东西我也没看懂.......我是看代码才明白的QAQ

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#define inf 2147483647
using namespace std;
const int Mx=1000010;
int n,m,root,a[Mx],l[Mx],r[Mx];
int tot,lson[Mx],rson[Mx],val[Mx],lazy[Mx],sum[Mx],Mnhis[Mx];
int Val[Mx],Lazy[Mx],Sum[Mx];//次小值 

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); }
    return x*f;
}

void pushup(int x)
{
    int L=lson[x],R=rson[x];
    Mnhis[x]=min(Mnhis[L],Mnhis[R]);
    val[x]=min(val[L],val[R]);
    if(val[L]!=val[R])
        Val[x]=min(max(val[L],val[R]),min(Val[L],Val[R]));
    else
        Val[x]=min(Val[L],Val[R]);
}

void build(int &x,int L,int R)
{
    x=++tot,l[x]=L,r[x]=R;
    if(L==R)
        val[x]=a[L],Val[x]=inf,Mnhis[x]=val[x];
    else
    {
        int mid=(L+R)/2;
        build(lson[x],L,mid);
        build(rson[x],mid+1,R);
        pushup(x);
    }
}

void Push(int x,int i,bool flag)
{
    int la=lazy[i],La=Lazy[i],su=sum[i],Su=Sum[i];
    if(!flag) la=La,su=Su;
    Mnhis[x]=min(Mnhis[x],val[x]+su);
    val[x]+=la; if(Val[x]!=inf) Val[x]+=La;
    sum[x]=min(sum[x],lazy[x]+su),Sum[x]=min(Sum[x],Lazy[x]+Su);
    lazy[x]+=la,Lazy[x]+=La;
}

void pushdown(int x)
{
    if(!lazy[x]&&!Lazy[x]&&sum[x]>=0&&Sum[x]>=0) return ;
    int L=lson[x],R=rson[x];
    if(val[L]==val[R]) Push(L,x,1),Push(R,x,1);
    if(val[L]<val[R]) Push(L,x,1),Push(R,x,0);
    if(val[L]>val[R]) Push(L,x,0),Push(R,x,1);
    lazy[x]=Lazy[x]=sum[x]=Sum[x]=0;
}

void Add(int x,int ll,int rr,int c)
{
    int L=l[x],R=r[x];
    if(L>rr||R<ll) return ;
    if(ll<=L&&rr>=R)
    {
        val[x]+=c; if(Val[x]!=inf) Val[x]+=c;
        lazy[x]+=c,Lazy[x]+=c;
        sum[x]=min(sum[x],lazy[x]),Sum[x]=min(Sum[x],Lazy[x]);
        Mnhis[x]=min(Mnhis[x],val[x]);
    }
    else
    {
        pushdown(x);
        Add(lson[x],ll,rr,c);
        Add(rson[x],ll,rr,c);
        pushup(x);
    }
}

void Max(int x,int ll,int rr,int c)
{
    int L=l[x],R=r[x];
    if(L>rr||R<ll) return ;
    if(ll<=L&&rr>=R&&Val[x]>c)
    {
        if(val[x]<c)
        {
            lazy[x]+=c-val[x];
            val[x]=c;
        }
    }
    else
    {
        pushdown(x);
        Max(lson[x],ll,rr,c);
        Max(rson[x],ll,rr,c);
        pushup(x);
    }
}

int Query(int x,int ll,int rr,bool flag)
{
    int L=l[x],R=r[x];
    if(L>rr||R<ll) return inf;
    if(ll<=L&&rr>=R)
    {
        if(flag) return Mnhis[x];
        else return val[x];
    }
    else
    {
        pushdown(x);
        int ans=min(Query(lson[x],ll,rr,flag),Query(rson[x],ll,rr,flag));
        pushup(x);
        return ans;
    }
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++) a[i]=read();;
    build(root,1,n);
    for(int i=1,num,x,y,z;i<=m;i++)
    {
        scanf("%d%d%d",&num,&x,&y);
        if(num==1) z=read(),Add(root,x,y,z);
        if(num==2) z=read(),Max(root,x,y,z);
        if(num==3) printf("%d\n",Query(root,x,y,0));
        if(num==4) printf("%d\n",Query(root,x,y,1));
    }
    return 0;
}

 

posted @ 2017-03-27 10:50  Czarina  阅读(308)  评论(0编辑  收藏  举报