BZOJ4695: 最假女选手

我好像被卡空间了啊?
惨啊..
代码好丑啊QAQ
考虑更新
类似VEB Tree的记录当前最大值
不过这样子还是不容易更新最小值的 于是记录一个次大值 和最大值个数便于更新
对于最大值用类似方法维护

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
char c;
#define ll long long
bool flag;
inline void read(int&a)
{
    a=0;do c=getchar();while(c!='-'&&(c<'0'||c>'9'));
    c=c=='-'?flag=true,getchar():c;
    while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar();
    a=flag?flag=false,-a:a;
}
const
    int INF=1<<29;
struct Seg
{
    int maxtime,fmax,smax;
    //int l,r;
    int mintime,fmin,smin;
    int maxtag,mintag,addtag;
    ll sum;
    Seg(){}
    Seg(int data):
        maxtag(-INF),fmax(data),smax(-INF),maxtime(1),
        mintag(-INF),fmin(data),smin(INF),mintime(1),
        addtag(0),sum(data)
        //l(l),r(r)
        {}
}T[2000001];
void Min(int&a,int b){a<b?a:a=b;}
void Max(int&a,int b){a>b?a:a=b;}
void MinTag(int place,int tag,int L,int R)
{
    if(T[place].fmax<=tag)return;
    T[place].sum-=(T[place].fmax-tag)*1ll*T[place].maxtime;
    T[place].fmax=tag;
    //Min(T[place].fmin,tag);
    if(R-L+1==T[place].maxtime)
        Min(T[place].fmin,tag);
    else Min(T[place].smin,tag);

    T[place].mintag=tag;
    if(T[place].maxtag^-INF)
        if(T[place].maxtag>T[place].mintag)
            T[place].maxtag=T[place].mintag;
}
void MaxTag(int place,int tag,int L,int R)
{
    if(T[place].fmin>=tag)return;
    T[place].sum-=(T[place].fmin-tag)*1ll*T[place].mintime;
    T[place].fmin=tag;
    if(R-L+1==T[place].maxtime)
        Max(T[place].fmax,tag);
    else Max(T[place].smax,tag);

    T[place].maxtag=tag;
    if(T[place].mintag^-INF)
        if(T[place].maxtag>T[place].mintag)
            T[place].mintag=T[place].maxtag;
}

void AddTag(int place,int tag,int L,int R)
{
    T[place].sum+=tag*1ll*(R-L+1);
    T[place].fmax+=tag;
    if(R-L+1!=T[place].maxtime)
        T[place].smax+=tag;
    T[place].fmin+=tag;

    if(R-L+1!=T[place].maxtime)
        T[place].smin+=tag;
    //T[place].smin+=tag;
    T[place].addtag+=tag;
    if(T[place].maxtag!=-INF)
            T[place].maxtag+=tag;
    if(T[place].mintag!=-INF)
            T[place].mintag+=tag;
}
void Push(int place,int L,int R)
{
    int mid=L+R>>1;

    if(T[place].addtag)
    {
        AddTag(place<<1,T[place].addtag,L,mid);
        AddTag(place<<1|1,T[place].addtag,mid+1,R);
        T[place].addtag=0;
    }
    if(T[place].maxtag^-INF)
    {
        MaxTag(place<<1,T[place].maxtag,L,mid);
        MaxTag(place<<1|1,T[place].maxtag,mid+1,R);
        T[place].maxtag=-INF;
    }
    if(T[place].mintag^-INF)
    {
        MinTag(place<<1,T[place].mintag,L,mid);
        MinTag(place<<1|1,T[place].mintag,mid+1,R);
        T[place].mintag=-INF;
    }

}

void Up(int place)
{
    T[place].maxtime=T[place].mintime=0;
    int lc=place<<1,rc=lc|1;
    T[place].sum=T[lc].sum+T[rc].sum;
    if(T[lc].fmax==T[rc].fmax)
    {
        T[place].fmax=T[rc].fmax;
        T[place].maxtime=T[lc].maxtime+T[rc].maxtime;
        T[place].smax=max(T[lc].smax,T[rc].smax);
    }
    else if(T[lc].fmax>T[rc].fmax)
    {
        T[place].fmax=T[lc].fmax;
        T[place].maxtime=T[lc].maxtime;
        T[place].smax=max(T[lc].smax,T[rc].fmax);
    }
    else
    {
        T[place].fmax=T[rc].fmax;
        T[place].maxtime=T[rc].maxtime;
        T[place].smax=max(T[rc].smax,T[lc].fmax);
    }

     if(T[lc].fmin==T[rc].fmin)
    {
        T[place].fmin=T[rc].fmin;
        T[place].mintime=T[lc].mintime+T[rc].mintime;
        T[place].smin=min(T[lc].smin,T[rc].smin);
    }
    else if(T[lc].fmin<T[rc].fmin)
    {
        T[place].fmin=T[lc].fmin;
        T[place].mintime=T[lc].mintime;
        T[place].smin=min(T[lc].smin,T[rc].fmin);
    }
    else
    {
        T[place].fmin=T[rc].fmin;
        T[place].mintime=T[rc].mintime;
        T[place].smin=min(T[rc].smin,T[lc].fmin);
    }
}


void MIN(int place,int l,int r,int p,int L,int R)
{
    if(T[place].fmax<=p){return;}
    if(L>=l&&R<=r&&T[place].fmax>p&&T[place].smax<p)
    {return MinTag(place,p,L,R);}
    Push(place,L,R);
    int Mid=L+R>>1;
    if(l<=Mid)MIN(place<<1,l,r,p,L,Mid);
    if(r>Mid)MIN(place<<1|1,l,r,p,Mid+1,R);
    Up(place);
}

void MAX(int place,int l,int r,int p,int L,int R)
{
    if(T[place].fmin>=p){return;}
    if(L>=l&&R<=r&&T[place].fmin<p&&T[place].smin>p)
    {return MaxTag(place,p,L,R);}
    Push(place,L,R);
    int Mid=L+R>>1;
    if(l<=Mid)MAX(place<<1,l,r,p,L,Mid);
    if(r>Mid)MAX(place<<1|1,l,r,p,Mid+1,R);
    Up(place);
}
void Add(int place,int l,int r,int tag,int L,int R)
{
    if(L>=l&&R<=r)return AddTag(place,tag,L,R);
    Push(place,L,R);
    int mid=L+R>>1;
    if(mid>=l)Add(place<<1,l,r,tag,L,mid);
    if(mid<r)Add(place<<1|1,l,r,tag,mid+1,R);
    Up(place);
}

ll Sum(int place,int l,int r,int L,int R)
{
    if(L>=l&&R<=r)return T[place].sum;
    Push(place,L,R);

    int mid=L+R>>1;
    ll res=0;
    if(mid>=l)res+=Sum(place<<1,l,r,L,mid);
    if(mid<r)res+=Sum(place<<1|1,l,r,mid+1,R);
    return res;
}

int Querymin(int place,int l,int r,int L,int R)
{
    if(L>=l&&R<=r)return T[place].fmin;
    Push(place,L,R);

    int mid=L+R>>1;
    int res=INF;
    if(mid>=l)Min(res,Querymin(place<<1,l,r,L,mid));
    if(mid<r)Min(res,Querymin(place<<1|1,l,r,mid+1,R));
    return res;
}

int Querymax(int place,int l,int r,int L,int R)
{
    if(L>=l&&R<=r)return T[place].fmax;
    int mid=L+R>>1;
    Push(place,L,R);
    int res=-INF;
    if(mid>=l)Max(res,Querymax(place<<1,l,r,L,mid));
    if(mid<r)Max(res,Querymax(place<<1|1,l,r,mid+1,R));
    return res;
}


int Data[1000001];
void Build(int place,int l,int r)
{
    T[place]=Seg(Data[l]);
    if(l^r)
    Build(place<<1,l,r+l>>1),Build(place<<1|1,1+(r+l>>1),r),Up(place);
}
void out(ll a)
{
    if(a<0)putchar('-'),a=-a;
    if(a>9)out(a/10);
    putchar('0'+a%10);
}


int main()
{
        int n,m;
        read(n);
        for(int i=1;i<=n;i++)read(Data[i]);
        Build(1,1,n);
        read(m);

        while(m--)
        {
    /*      //if(!m)
            {puts("   **************  ");
            puts("   **************  ");
            puts("   **************  ");
            puts("   **************  ");
            Print(1,1,n);
            puts("   **************  ");
            puts("   **************  ");
            puts("   **************  ");
            puts("   **************  ");
            puts("   **************  ");
    }*/
            int op;read(op);
            int l,r,t;
            read(l),read(r);
            if(op==1)read(t),Add(1,l,r,t,1,n);
            else if(op==2)read(t),MAX(1,l,r,t,1,n);
            else if(op==3)read(t),MIN(1,l,r,t,1,n);
            else if(op==4)out(Sum(1,l,r,1,n)),putchar('\n');
            else if(op==5)out(Querymax(1,l,r,1,n)),putchar('\n');
            else    out(Querymin(1,l,r,1,n)),putchar('\n');

        }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值