luoguP5073 [Ynoi Easy Round 2015] 世上最幸福的女孩 题解

准备写分块,被同学喊来写末日三问,这是弱化版。

考虑处理这个问题,对于正常的区间最大子段和,我们显然可以直接线段树去维护,这道题目多了一个区间加,我们的最大子段和就和长度有了关系,对于每一个节点维护凸包,对于左子树的右儿子和右子树的左儿子做闵可夫斯基和就可以了,对于时间只有\(O(n\log n)\),我们可以提前按全局增加的数值排序,然后凸包直接用指针扫过去,对于空间只有\(O(n)\),我们可以考虑在建线段树的时候动态处理答案,并且把询问用类似于整体二分的写法下方(就是有序的序列不断地分裂,或者用归并线性合并两个有序序列。)

#include <bits/stdc++.h>
#define lll long long
#define fw fwrite(obuf,p3-obuf,1,stdout)
#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin),p1==p2)?EOF:*p1++)
#define putchar(x) (p3-obuf<1<<20?(*p3++=(x)):(fw,p3=obuf,*p3++=(x)))
using namespace std;

char buf[1<<20],obuf[1<<20],*p1=buf,*p2=buf,*p3=obuf,str[20<<2];
lll read(){
	lll x=0,f=1;
	char ch=getchar();
	while(!isdigit(ch))ch=='-'&&(f=-1),ch=getchar();
	while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
	return x*f;
}
template<typename T>
void write(T x,char sf='\n'){
	if(x<0)putchar('-'),x=~x+1;
	lll top=0;
	do str[top++]=x%10,x/=10;while(x);
	while(top)putchar(str[--top]+48);
	if(sf^'#')putchar(sf);
}
inline lll max(lll a,lll b){
	return a>b?a:b;
}
constexpr lll maxn=6e5+10;
constexpr lll INF=0x3f3f3f3f3f3f3f3fll,IINF=0xc0c0c0c0c0c0c0c0ll;
lll tg,ans[maxn],pre[maxn],val1,val2,tp,V[maxn];
int n,m,op,x,y,ttp,a[maxn],L,R,ll,rr,tt[maxn],lin[maxn];
pair<int,lll>st[maxn<<1];
vector<pair<int,lll> >f[210],g[210],h[210];
struct edge{
	int l;
	int r;
	lll k;
	int id;
}wen[maxn];
inline bool cmp(edge q,edge w){
	return q.k<w.k;
}
inline lll val(lll q,pair<int,lll> w){
	return q*w.first+w.second;
}
inline void querys(int id,int idd){
	int nowf=0,nowg=0,nowh=0;
	for(int i=1;i<=id;i++){
		while(nowf<f[idd].size()-1&&val(wen[tt[i]].k,f[idd][nowf])<val(wen[tt[i]].k,f[idd][nowf+1])){
			nowf++;
		}
		while(nowg<g[idd].size()-1&&val(wen[tt[i]].k,g[idd][nowg])<val(wen[tt[i]].k,g[idd][nowg+1])){
			nowg++;
		}
		while(nowh<h[idd].size()-1&&val(wen[tt[i]].k,h[idd][nowh])<val(wen[tt[i]].k,h[idd][nowh+1])){
			nowh++;
		}
		ans[wen[tt[i]].id]=max(ans[wen[tt[i]].id],val(wen[tt[i]].k,f[idd][nowf])+pre[wen[tt[i]].id]);
		ans[wen[tt[i]].id]=max(ans[wen[tt[i]].id],val(wen[tt[i]].k,h[idd][nowh]));
		pre[wen[tt[i]].id]=max(pre[wen[tt[i]].id]+val(wen[tt[i]].k,g[idd][g[idd].size()-1]),val(wen[tt[i]].k,g[idd][nowg]));
	}
	return;
}
inline void clean(int id){
	vector<pair<int,lll> >().swap(f[id]);
	vector<pair<int,lll> >().swap(g[id]);
	vector<pair<int,lll> >().swap(h[id]);
	return;
}
inline void pai(vector<pair<int,lll> >&q){
	for(int i=1;i<=tp;i++){
		while(q.size()&&q.back().first==st[i].first&&q.back().second<=st[i].second){
			q.pop_back();
		}
		while(q.size()>1&&(q[q.size()-1].second-q[q.size()-2].second)*(q[q.size()-1].first-st[i].first)>
		(q[q.size()-2].first-q[q.size()-1].first)*(st[i].second-q[q.size()-1].second)){
			q.pop_back();
		}
		q.emplace_back(st[i]);
	}
	tp=0;
	return;
}
int cmp1(int q,int w){
	if(wen[q].k!=wen[w].k){
		return wen[q].k<wen[w].k;
	}
	return wen[q].id<wen[w].id;
}
inline void get(int l,int r,int qw,int wq){
	if(l==r){
		f[qw].emplace_back(1,a[l]);
		g[qw].emplace_back(1,a[l]);
		h[qw].emplace_back(1,a[l]);
		querys(wq,qw);
		return;
	}
	int mid=(l+r)>>1;
	int ll3=0,ll4=0,ll5=0;
	L=0,R=wq+1;
	for(lll i=1;i<=wq;i++){
		if(wen[tt[i]].l>l||r>wen[tt[i]].r){
			L++;
			lin[L]=tt[i];
		}
		else{
			R--;
			lin[R]=tt[i];
		}
	}
	memcpy(tt,lin,(wq+1)<<2);
	ll5=wq-R+1;
	wq=L;
	L=0,R=wq+1;
	for(lll i=1;i<=wq;i++){
		if((wen[tt[i]].l>l||r>wen[tt[i]].r)&&wen[tt[i]].l<=mid){
			L++;
			lin[L]=tt[i];
		}
		else{
			R--;
			lin[R]=tt[i];
		}
	}
	memcpy(tt,lin,(wq+1)<<2);
	ll3=L;
	get(l,mid,qw+1,L);
	memcpy(lin,tt,(wq+1)<<2);
	L=1,R=wq,ll4=0;
	while(L<=ll3||R>ll3){
		if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
			tt[++ll4]=lin[L];
			L++;
		}
		else{
			tt[++ll4]=lin[R];
			R--;
		}
	}
	L=0,R=wq+1;
	for(lll i=1;i<=wq;i++){
		if((wen[tt[i]].l>l||r>wen[tt[i]].r)&&wen[tt[i]].r>mid){
			L++;
			lin[L]=tt[i];
		}
		else{
			R--;
			lin[R]=tt[i];
		}
	}
	memcpy(tt,lin,(wq+1)<<2);
	ll3=L;
	get(mid+1,r,qw+2,L);
	memcpy(lin,tt,(wq+1)<<2);
	L=1,R=wq,ll4=0;
	while(L<=ll3||R>ll3){
		if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
			tt[++ll4]=lin[L];
			L++;
		}
		else{
			tt[++ll4]=lin[R];
			R--;
		}
	}
	reverse(tt+1,tt+wq+1);
	lll ll1=0,ll2=0;
	ll1=f[qw+1][f[qw+1].size()-1].first;
	ll2=f[qw+1][f[qw+1].size()-1].second;
	for(auto x:f[qw+1]) f[qw].emplace_back(x);
	for(auto x:f[qw+2]) st[++tp]={ll1+x.first,ll2+x.second};
	pai(f[qw]);
	ll1=g[qw+2][g[qw+2].size()-1].first;
	ll2=g[qw+2][g[qw+2].size()-1].second;
	for(auto x:g[qw+2]) g[qw].emplace_back(x);
	for(auto x:g[qw+1]) st[++tp]={ll1+x.first,ll2+x.second};
	pai(g[qw]);
	L=1,R=1,val1=g[qw+1][0].second,val2=f[qw+2][0].second,ll=g[qw+1][0].first,rr=f[qw+2][0].first;
	st[++tp]={ll+rr,val1+val2};
	while(L<g[qw+1].size()||R<f[qw+2].size()){
		if(R==f[qw+2].size()||(L<g[qw+1].size()&&(g[qw+1][L].second-val1)*(f[qw+2][R].first-rr)>(f[qw+2][R].second-val2)*(g[qw+1][L].first-ll))){
			val1=g[qw+1][L].second;
			ll=g[qw+1][L].first;
			L++;
		}
		else{
			val2=f[qw+2][R].second;
			rr=f[qw+2][R].first;
			R++;
		}
		st[++tp]={ll+rr,val1+val2};
	}
	for(auto x:h[qw+1]) st[++tp]=x;
	for(auto x:h[qw+2]) st[++tp]=x;
	memset(V,0xc0,(r-l+2)<<3);
	for(lll i=1;i<=tp;i++){
		V[st[i].first]=max(V[st[i].first],st[i].second);
	}
	tp=0;
	for(lll i=1;i<=r-l+1;i++){
		if(V[i]!=IINF){
			st[++tp]={i,V[i]};
		}
	}
	pai(h[qw]);
	clean(qw+1);
	clean(qw+2);
	wq+=ll5;
	reverse(tt+1,tt+wq+1);
	reverse(tt+ll5+1,tt+wq+1);
	querys(ll5,qw);
	memcpy(lin,tt,(wq+1)<<2);
	ll3=ll5;
	L=1,R=wq,ll4=0;
	while(L<=ll3||R>ll3){
		if(R<=ll3||(L<=ll3&&lin[L]<lin[R])){
			tt[++ll4]=lin[L];
			L++;
		}
		else{
			tt[++ll4]=lin[R];
			R--;
		}
	}
	return;
}
signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;i++){
		a[i]=read();
	}
	for(int i=1;i<=m;i++){
		op=read();
		if(op==1){
			x=read();
			tg+=x;
		}
		else{
			x=read(),y=read();
			wen[++ttp]={x,y,tg,ttp};
		}
	}
	sort(wen+1,wen+1+ttp,cmp);
	for(int i=1;i<=ttp;i++){
		tt[i]=i;
	}
	get(1,n,1,ttp);
	for(int i=1;i<=ttp;i++){
		write(ans[i]);
	}
	return fw,0;
}
posted @ 2025-07-21 16:42  特别之处  阅读(39)  评论(0)    收藏  举报