题目链接
https://www.lydsy.com/JudgeOnline/problem.php?id=4695
思路
恶心题……思路请见2016年国家候选队论文《区间最值操作与历史最值问题——吉如一》
代码
#include <cstdio>
#include <algorithm>
const int maxn=500000;
const int inf=0x3f3f3f3f;
int read()
{
int x=0,f=1;
char ch=getchar();
while((ch<'0')||(ch>'9'))
{
if(ch=='-')
{
f=-f;
}
ch=getchar();
}
while((ch>='0')&&(ch<='9'))
{
x=x*10+ch-'0';
ch=getchar();
}
return x*f;
}
int n,a[maxn+10];
namespace smt
{
struct node
{
int mx,mn,smx,smn,nmx,nmn,tmx,tmn,adt;
long long sum;
};
node val[maxn<<2];
inline int putadt(int x,int l,int r,int adv)
{
node* now=&val[x];
now->mx+=adv;
now->mn+=adv;
if(now->smx!=-inf)
{
now->smx+=adv;
}
if(now->smn!=inf)
{
now->smn+=adv;
}
now->sum+=1ll*(r-l+1)*adv;
now->adt+=adv;
if(now->tmx!=inf)
{
now->tmx+=adv;
}
if(now->tmx!=-inf)
{
now->tmn+=adv;
}
return 0;
}
inline int puttmx(int x,int cval)
{
node* now=&val[x];
now->sum-=1ll*(now->mx-cval)*now->nmx;
now->mx=now->tmx=cval;
if(cval<now->mn)
{
now->mn=cval;
}
if((now->smn!=inf)&&(cval<now->smn))
{
now->smn=cval;
}
if((now->tmn!=-inf)&&(now->tmn>cval))
{
now->tmn=cval;
}
return 0;
}
inline int puttmn(int x,int cval)
{
node* now=&val[x];
now->sum+=1ll*(cval-now->mn)*now->nmn;
now->mn=now->tmn=cval;
if(cval>now->mx)
{
now->mx=cval;
}
if((now->smx!=-inf)&&(cval>now->smx))
{
now->smx=cval;
}
if((now->tmx!=inf)&&(now->tmx<cval))
{
now->tmx=cval;
}
return 0;
}
inline int pushdown(int x,int l,int r)
{
node* now=&val[x];
node* ls=&val[x<<1];
node* rs=&val[x<<1|1];
int mid=(l+r)>>1;
if(now->adt!=0)
{
putadt(x<<1,l,mid,now->adt);
putadt(x<<1|1,mid+1,r,now->adt);
now->adt=0;
}
if(now->tmx!=inf)
{
if(ls->mx>now->mx)
{
puttmx(x<<1,now->tmx);
}
if(rs->mx>now->mx)
{
puttmx(x<<1|1,now->tmx);
}
now->tmx=inf;
}
if(now->tmn!=-inf)
{
if(ls->mn<now->mn)
{
puttmn(x<<1,now->tmn);
}
if(rs->mn<now->mn)
{
puttmn(x<<1|1,now->tmn);
}
now->tmn=-inf;
}
return 0;
}
inline int updata(int x)
{
node* now=&val[x];
node* ls=&val[x<<1];
node* rs=&val[x<<1|1];
now->mx=std::max(ls->mx,rs->mx);
now->mn=std::min(ls->mn,rs->mn);
now->smx=-inf;
if(ls->mx!=now->mx)
{
now->smx=std::max(ls->mx,now->smx);
}
if(rs->mx!=now->mx)
{
now->smx=std::max(rs->mx,now->smx);
}
now->smx=std::max(now->smx,std::max(ls->smx,rs->smx));
now->smn=inf;
if(ls->mn!=now->mn)
{
now->smn=std::min(ls->mn,now->smn);
}
if(rs->mn!=now->mn)
{
now->smn=std::min(rs->mn,now->smn);
}
now->smn=std::min(now->smn,std::min(ls->smn,rs->smn));
now->nmx=now->nmn=0;
if(ls->mx==now->mx)
{
now->nmx+=ls->nmx;
}
if(rs->mx==now->mx)
{
now->nmx+=rs->nmx;
}
if(ls->mn==now->mn)
{
now->nmn+=ls->nmn;
}
if(rs->mn==now->mn)
{
now->nmn+=rs->nmn;
}
now->sum=ls->sum+rs->sum;
return 0;
}
int build(int x,int l,int r)
{
node* now=&val[x];
if(l==r)
{
now->mx=now->mn=now->sum=a[l];
now->smx=now->tmn=-inf;
now->smn=now->tmx=inf;
now->nmx=now->nmn=1;
now->adt=0;
return 0;
}
int mid=(l+r)>>1;
build(x<<1,l,mid);
build(x<<1|1,mid+1,r);
now->tmx=inf;
now->tmn=-inf;
updata(x);
return 0;
}
int add(int x,int l,int r,int askl,int askr,int adv)
{
if((askl<=l)&&(r<=askr))
{
putadt(x,l,r,adv);
return 0;
}
pushdown(x,l,r);
int mid=(l+r)>>1;
if(askl<=mid)
{
add(x<<1,l,mid,askl,askr,adv);
}
if(mid<askr)
{
add(x<<1|1,mid+1,r,askl,askr,adv);
}
updata(x);
return 0;
}
long long getsum(int x,int l,int r,int askl,int askr)
{
if((askl<=l)&&(r<=askr))
{
return val[x].sum;
}
pushdown(x,l,r);
int mid=(l+r)>>1;
long long res=0;
if(askl<=mid)
{
res+=getsum(x<<1,l,mid,askl,askr);
}
if(mid<askr)
{
res+=getsum(x<<1|1,mid+1,r,askl,askr);
}
return res;
}
int getmax(int x,int l,int r,int askl,int askr)
{
if((askl<=l)&&(r<=askr))
{
return val[x].mx;
}
pushdown(x,l,r);
int mid=(l+r)>>1,res=-inf;
if(askl<=mid)
{
res=std::max(res,getmax(x<<1,l,mid,askl,askr));
}
if(mid<askr)
{
res=std::max(res,getmax(x<<1|1,mid+1,r,askl,askr));
}
return res;
}
int getmin(int x,int l,int r,int askl,int askr)
{
if((askl<=l)&&(r<=askr))
{
return val[x].mn;
}
pushdown(x,l,r);
int mid=(l+r)>>1,res=inf;
if(askl<=mid)
{
res=std::min(res,getmin(x<<1,l,mid,askl,askr));
}
if(mid<askr)
{
res=std::min(res,getmin(x<<1|1,mid+1,r,askl,askr));
}
return res;
}
int changemax(int x,int l,int r,int askl,int askr,int cval)
{
int mid=(l+r)>>1;
if((askl<=l)&&(r<=askr))
{
if(cval>=val[x].mx)
{
return 0;
}
else if(cval>val[x].smx)
{
puttmx(x,cval);
}
else
{
pushdown(x,l,r);
changemax(x<<1,l,mid,askl,askr,cval);
changemax(x<<1|1,mid+1,r,askl,askr,cval);
updata(x);
}
return 0;
}
pushdown(x,l,r);
if(askl<=mid)
{
changemax(x<<1,l,mid,askl,askr,cval);
}
if(mid<askr)
{
changemax(x<<1|1,mid+1,r,askl,askr,cval);
}
updata(x);
return 0;
}
int changemin(int x,int l,int r,int askl,int askr,int cval)
{
int mid=(l+r)>>1;
if((askl<=l)&&(r<=askr))
{
if(cval<=val[x].mn)
{
return 0;
}
else if(cval<val[x].smn)
{
puttmn(x,cval);
}
else
{
pushdown(x,l,r);
changemin(x<<1,l,mid,askl,askr,cval);
changemin(x<<1|1,mid+1,r,askl,askr,cval);
updata(x);
}
return 0;
}
pushdown(x,l,r);
if(askl<=mid)
{
changemin(x<<1,l,mid,askl,askr,cval);
}
if(mid<askr)
{
changemin(x<<1|1,mid+1,r,askl,askr,cval);
}
updata(x);
return 0;
}
}
int main()
{
n=read();
for(int i=1; i<=n; ++i)
{
a[i]=read();
}
smt::build(1,1,n);
int m=read();
while(m--)
{
int op=read(),l=read(),r=read(),x=0;
if(op<=3)
{
x=read();
}
if(op==1)
{
smt::add(1,1,n,l,r,x);
}
else if(op==2)
{
smt::changemin(1,1,n,l,r,x);
}
else if(op==3)
{
smt::changemax(1,1,n,l,r,x);
}
else if(op==4)
{
printf("%lld\n",smt::getsum(1,1,n,l,r));
}
else if(op==5)
{
printf("%d\n",smt::getmax(1,1,n,l,r));
}
else
{
printf("%d\n",smt::getmin(1,1,n,l,r));
}
}
return 0;
}