BZOJ4695: 最假女选手

BZOJ4695: 最假女选手

https://lydsy.com/JudgeOnline/problem.php?id=4695

分析:

  • 维护区间最小值,次小值,最小值个数,最大值,次大值,最大值个数,区间加标记,区间和。
  • 其中对于最小值增加的操作我们直接对当前结点的最小值修改。
  • 下传时如果儿子的最小值小于当前结点的最小值就修改掉,最大值同理。
  • 由于修改最小值时可能会影响最大值或次大值,顺便维护一下即可。

代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
#define N 500050
#define ls p<<1
#define rs p<<1|1
typedef long long ll;
int n,m,a[N];
const int inf = 1<<30;
int mn1[N<<2],mn2[N<<2],mx1[N<<2],mx2[N<<2],tag1[N<<2],tag2[N<<2],tag3[N<<2],cmn[N<<2],cmx[N<<2],len[N<<2];
ll sum[N<<2];
char buf[100000],*p1,*p2;
#define nc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++)
int rd() {
	int x=0,f=1; char s=nc();
	while(s<'0'||s>'9') {if(s=='-')f=-1;s=nc();}
	while(s>='0'&&s<='9') x=(((x<<2)+x)<<1)+s-'0',s=nc();
	return x*f;
}
inline void pushup(int p) {
	mn1[p]=min(mn1[ls],mn1[rs]);
	if(mn1[ls]==mn1[rs]) mn2[p]=min(mn2[ls],mn2[rs]),cmn[p]=cmn[ls]+cmn[rs];
	else if(mn1[ls]<mn1[rs]) mn2[p]=min(mn2[ls],mn1[rs]),cmn[p]=cmn[ls];
	else mn2[p]=min(mn1[ls],mn2[rs]),cmn[p]=cmn[rs];
	mx1[p]=max(mx1[ls],mx1[rs]);
	if(mx1[ls]==mx1[rs]) mx2[p]=max(mx2[ls],mx2[rs]),cmx[p]=cmx[ls]+cmx[rs];
	else if(mx1[ls]>mx1[rs]) mx2[p]=max(mx2[ls],mx1[rs]),cmx[p]=cmx[ls];
	else mx2[p]=max(mx1[ls],mx2[rs]),cmx[p]=cmx[rs];
	sum[p]=sum[ls]+sum[rs];
}
inline void giv1(int p,ll v) {
	tag1[p]+=v; sum[p]+=len[p]*v;
	mn1[p]+=v; mn2[p]+=v; mx1[p]+=v; mx2[p]+=v;
}
inline void giv2(int p,ll v) {
	sum[p]+=cmn[p]*(v-mn1[p]);
	if(mx1[p]==mn1[p]) mx1[p]=v;
	if(mx2[p]==mn1[p]) mx2[p]=v;
	mn1[p]=v;
}
inline void giv3(int p,ll v) {
	sum[p]+=cmx[p]*(v-mx1[p]);
	if(mn1[p]==mx1[p]) mn1[p]=v;
	if(mn2[p]==mx1[p]) mn2[p]=v;
	mx1[p]=v;
}
inline void pushdown(int p) {
	if(tag1[p]) giv1(ls,tag1[p]),giv1(rs,tag1[p]),tag1[p]=0;
	if(mn1[ls]<mn1[p]) giv2(ls,mn1[p]);
	if(mn1[rs]<mn1[p]) giv2(rs,mn1[p]);
	if(mx1[ls]>mx1[p]) giv3(ls,mx1[p]);
	if(mx1[rs]>mx1[p]) giv3(rs,mx1[p]);
}
void build(int l,int r,int p) {
	len[p]=r-l+1;
	if(l==r) {
		mn1[p]=mx1[p]=sum[p]=a[l]; cmn[p]=cmx[p]=1;
		mn2[p]=inf; mx2[p]=-inf;
		return ;
	}
	int mid=(l+r)>>1;
	build(l,mid,ls),build(mid+1,r,rs);
	pushup(p);
}
void updadd(int l,int r,int x,int y,int v,int p) {
	if(x<=l&&y>=r) {giv1(p,v); return ;}
	int mid=(l+r)>>1; pushdown(p);
	if(x<=mid) updadd(l,mid,x,y,v,ls);
	if(y>mid) updadd(mid+1,r,x,y,v,rs);
	pushup(p);
}
void updmax(int l,int r,int x,int y,int v,int p) {
	if(mn1[p]>=v) return ;
	if(x<=l&&y>=r&&mn2[p]>v) {giv2(p,v); return ;}	
	if(l==r) {mn1[p]=mx1[p]=sum[p]=v; mn2[p]=inf; mx2[p]=-inf; return ;}
	int mid=(l+r)>>1; pushdown(p);
	if(x<=mid) updmax(l,mid,x,y,v,ls);
	if(y>mid) updmax(mid+1,r,x,y,v,rs);
	pushup(p);
}
void updmin(int l,int r,int x,int y,int v,int p) {
	if(mx1[p]<=v) return ;
	if(x<=l&&y>=r&&mx2[p]<v) {giv3(p,v); return ;}
	if(l==r) {mn1[p]=mx1[p]=sum[p]=v; mn2[p]=inf; mx2[p]=-inf; return ;}
	int mid=(l+r)>>1; pushdown(p);
	if(x<=mid) updmin(l,mid,x,y,v,ls);
	if(y>mid) updmin(mid+1,r,x,y,v,rs);
	pushup(p);
}
ll get_s(int l,int r,int x,int y,int p) {
	if(x<=l&&y>=r) return sum[p];
	int mid=(l+r)>>1; pushdown(p); ll re=0;
	if(x<=mid) re+=get_s(l,mid,x,y,ls);
	if(y>mid) re+=get_s(mid+1,r,x,y,rs);
	return re;
}
int rmq(int l,int r,int x,int y,int p,int o) {
	if(x<=l&&y>=r) return o?mx1[p]:mn1[p];
	int mid=(l+r)>>1,re=o?(-inf):inf; pushdown(p);
	if(x<=mid) {
		int t=rmq(l,mid,x,y,ls,o);
		if(o) re=max(re,t);
		else re=min(re,t);
	}
	if(y>mid) {
		int t=rmq(mid+1,r,x,y,rs,o);
		if(o) re=max(re,t);
		else re=min(re,t);
	}
	return re;
}
int main() {
	n=rd();
	int i,opt,x,y,z;
	for(i=1;i<=n;i++) a[i]=rd();
	build(1,n,1);
	m=rd();
	while(m--) {
		opt=rd(),x=rd(),y=rd();
		if(opt==1) {
			z=rd(); updadd(1,n,x,y,z,1);
		}else if(opt==2) {
			z=rd(); updmax(1,n,x,y,z,1);
		}else if(opt==3) {
			z=rd(); updmin(1,n,x,y,z,1);
		}else if(opt==4) {
			printf("%lld\n",get_s(1,n,x,y,1));
		}else if(opt==5) {
			printf("%d\n",rmq(1,n,x,y,1,1));
		}else {
			printf("%d\n",rmq(1,n,x,y,1,0));
		}
	}
}
posted @ 2019-01-01 14:59  fcwww  阅读(192)  评论(0编辑  收藏  举报