您的位置:首页 > 其它

【UOJ#169】元旦老人与数列

2017-08-18 22:09 225 查看
论文题。

考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记。

我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值。

对于被覆盖一半的区间,讨论一下即可。

对于每个最小值和次小值记录前缀最小值,当前/历史最小值,当到达合法区间的时候:

如果区间最小值>x,直接退出。

如果minv[o]<x<semn[o],那么更新当前的次小值

反之继续向下。

#include<bits/stdc++.h>
const int inf=2e9+7;
const int N=500005;
using namespace std;
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;
}
int n,m;
struct Segment_Tree_Beats{
#define lson (o<<1)
#define rson (o<<1|1)
int his[N<<2],pra[N<<2],prb[N<<2],a[N<<2],b[N<<2],minv[N<<2],semn[N<<2];
inline void pushup(int o){
if(minv[lson]==minv[rson])minv[o]=minv[lson],semn[o]=min(semn[lson],semn[rson]);
else if(minv[lson]<minv[rson]){minv[o]=minv[lson];semn[o]=min(semn[lson],minv[rson]);}
else{minv[o]=minv[rson];semn[o]=min(semn[rson],minv[lson]);}
his[o]=min(his[lson],his[rson]);
}
inline void puttag(int o,int v){
his[o]=min(his[o],minv[o]+v);
a[o]+=v;b[o]+=v;minv[o]+=v;semn[o]+=v;semn[o]=min(semn[o],inf);
pra[o]=min(pra[o],a[o]);
prb[o]=min(prb[o],b[o]);
}
inline void plus(int o,int ax,int pa,int bx,int pb){
his[o]=min(his[o],minv[o]+pa);
pra[o]=min(pra[o],pa+a[o]);
prb[o]=min(prb[o],pb+b[o]);
a[o]+=ax;b[o]+=bx;minv[o]+=ax;semn[o]+=bx;semn[o]=min(semn[o],inf);
}
inline void pushdown(int o){
int mmmm=min(minv[lson],minv[rson]);
if(minv[lson]==mmmm)plus(lson,a[o],pra[o],b[o],prb[o]);else plus(lson,b[o],prb[o],b[o],prb[o]);
if(minv[rson]==mmmm)plus(rson,a[o],pra[o],b[o],prb[o]);else plus(rson,b[o],prb[o],b[o],prb[o]);
a[o]=b[o]=pra[o]=prb[o]=0;
}
inline void build(int o,int l,int r){
if(l==r){
minv[o]=read();his[o]=minv[o];semn[o]=inf;
return;
}
int mid=(l+r)>>1;
build(lson,l,mid);build(rson,mid+1,r);
pushup(o);
}
inline void optadd(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){puttag(o,v);return;}
int mid=(l+r)>>1;pushdown(o);
if(ql<=mid)optadd(lson,l,mid,ql,qr,v);
if(qr>mid)optadd(rson,mid+1,r,ql,qr,v);
pushup(o);
}
inline void dfs(int o,int l,int r,int v){
if(minv[o]>=v)return;
if(semn[o]>v){
v-=minv[o];his[o]=min(his[o],minv[o]+v);
pra[o]=min(pra[o],a[o]+v);
a[o]+=v;minv[o]+=v;return;
}
int mid=(l+r)>>1;pushdown(o);
dfs(lson,l,mid,v);dfs(rson,mid+1,r,v);
pushup(o);
}
inline void change(int o,int l,int r,int ql,int qr,int v){
if(ql<=l&&r<=qr){dfs(o,l,r,v);return;}
int mid=(l+r)>>1;pushdown(o);
if(ql<=mid)change(lson,l,mid,ql,qr,v);
if(qr>mid)change(rson,mid+1,r,ql,qr,v);
pushup(o);
}
inline int querynow(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return minv[o];
int mid=(l+r)>>1,ans=inf;pushdown(o);
if(ql<=mid)ans=min(ans,querynow(lson,l,mid,ql,qr));
if(qr>mid)ans=min(ans,querynow(rson,mid+1,r,ql,qr));
return ans;
}
inline int queryhis(int o,int l,int r,int ql,int qr){
if(ql<=l&&r<=qr)return his[o];
int mid=(l+r)>>1,ans=inf;pushdown(o);
if(ql<=mid)ans=min(ans,queryhis(lson,l,mid,ql,qr));
if(qr>mid)ans=min(ans,queryhis(rson,mid+1,r,ql,qr));
return ans;
}
}T;
int main(){
n=read();m=read();
T.build(1,1,n);
while(m--){
int opt=read(),l=read(),r=read();
if(opt==1){int x=read();T.optadd(1,1,n,l,r,x);}
if(opt==2){int x=read();T.change(1,1,n,l,r,x);}
if(opt==3)printf("%d\n",T.querynow(1,1,n,l,r));
if(opt==4)printf("%d\n",T.queryhis(1,1,n,l,r));
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: