把博客园图标替换成自己的图标
把博客园图标替换成自己的图标end

luogu P5044 [IOI2018] meetings 会议

题面传送门

现在看到最大值已经下意识建笛卡尔树了吗/youl

首先下意识把笛卡尔树建出来,然后设\(f_{i,j}\)表示\([i,j]\)区间内的答案,我们设\(x\)\([i,j]\)为在线段树上对应的节点,那么我们将\([i,j]\)区间的值挂在\(x\)节点上。

容易发现其实\(f_{i,j}\min(f_{i,x-1}+(j-x+1)A_x,f_{x+1,j}+(x-i+1)A_x)\)。所以我们只需要维护一个节点所对应区间的前缀答案与后缀答案即可回答询问了。

事实上在lg上只要暴力维护这个东西就能过因为笛卡尔树基本上随机

我们以维护前缀答案为例展示如何维护YZXAKIOI,首先左子树原来的前缀一定不变,中间这个节点max一定是它本身,所以从前面一个点转移显然最优。右边的前驱有两种选法,一是会议地点放在右边,则左边都要付出\(A_x\)的代价,这是个定值,或者放在左边,那么右边增加的代价相当于随位置递增的一条直线。也就是说,我们要维护区间与直线取\(\min\),和区间加。用李超树可以做到\(O(n\log ^2n)\)

但是这个复杂度并不优秀,因为这是一棵笛卡尔树,所以上面的权值一定大于下面的权值,这就意味着底下的斜率一定小于等于当前的\(A_x\),所以这条直线只会覆盖一段前缀,那么可以线段树上二分后区间覆盖即可,时间复杂度\(O((n+q)\log n)\)

code:

#include "meetings.h"
#include<bits/stdc++.h>
#define Gc() getchar() 
#define Me(x,y) memset(x,y,sizeof(x))
#define Mc(x,y) memcpy(x,y,sizeof(x))
#define d(x,y) ((k+1)*(x)+(y))
#define R(n) (rnd()%(n)+1)
#define Pc(x) putchar(x)
#define LB lower_bound
#define UB upper_bound
#define PB push_back
using ll=long long;using db=double;using lb=long db;using ui=unsigned;using ull=unsigned ll;
using namespace std;const int N=7.5e5+5,M=N*4+5,K=2e3+5,mod=998244353,Mod=mod-1;const db eps=1e-5;const int INF=1e9+7;
int n,m,k,x,y,z,L[N],R[N],st[N],H,Fr[N],En[N],fa[N][21],lg[N],d[N],X[N],Y[N],A[N];ll f[N],g[N],Ans[N];vector<int> S[N];
void Make(int x,int La){if(!x) return;d[x]=d[La]+1;fa[x][0]=La;for(int i=1;fa[x][i-1];i++) fa[x][i]=fa[fa[x][i-1]][i-1];Make(L[x],x);Make(R[x],x);}
int LCA(int x,int y){d[x]<d[y]&&(swap(x,y),0);while(d[x]^d[y]) x=fa[x][lg[d[x]-d[y]]];if(x==y) return x;for(int i=lg[d[x]];~i;i--) fa[x][i]^fa[y][i]&&(x=fa[x][i],y=fa[y][i]);return fa[x][0];}
namespace T1{
	#define ls v<<1
	#define rs v<<1|1
	int R[M],L[M];ll f[M],g[M],X[M],Y[M],s[M];void PF(int v,ll x,ll y){f[v]=x*R[v]+y;g[v]=x*L[v]+y;X[v]=x;Y[v]=y;s[v]=0;}void PS(int x,ll w){f[x]+=w;g[x]+=w;s[x]+=w;}void P(int v){X[v]&&(PF(ls,X[v],Y[v]),PF(rs,X[v],Y[v]),X[v]=Y[v]=0);s[v]&&(PS(ls,s[v]),PS(rs,s[v]),s[v]=0);}
	void BD(int l=1,int r=n,int v=1){R[v]=r;L[v]=l;if(l==r) return;int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);}void Up(int v){f[v]=f[rs];g[v]=g[ls];}
	void Ins(int x,ll y,int l=1,int r=n,int v=1){if(l==r) {f[v]=g[v]=y;return;}int m=l+r>>1;P(v);x<=m?Ins(x,y,l,m,ls):Ins(x,y,m+1,r,rs);Up(v);}
	ll Qry(int x,int l=1,int r=n,int v=1){if(l==r) return f[v];P(v);int m=l+r>>1;return x<=m?Qry(x,l,m,ls):Qry(x,m+1,r,rs);}
	void Add(int x,int y,ll A,ll B,int l=1,int r=n,int v=1){if(x<=l&&r<=y&&g[v]<=A*l+B) return;if(x<=l&&r<=y&&f[v]>=A*r+B) return PF(v,A,B);int m=l+r>>1;P(v);x<=m&&(Add(x,y,A,B,l,m,ls),0);y>m&&(Add(x,y,A,B,m+1,r,rs),0);Up(v);}
	void Mdf(int x,int y,ll z,int l=1,int r=n,int v=1){if(x<=l&&r<=y) return PS(v,z);int m=l+r>>1;P(v);x<=m&&(Mdf(x,y,z,l,m,ls),0);y>m&&(Mdf(x,y,z,m+1,r,rs),0);Up(v);}
	#undef ls
	#undef rs 
}
namespace T2{
	#define ls v<<1
	#define rs v<<1|1
	int R[M],L[M];ll f[M],g[M],X[M],Y[M],s[M];void PF(int v,ll x,ll y){f[v]=x*R[v]+y;g[v]=x*L[v]+y;X[v]=x;Y[v]=y;s[v]=0;}void PS(int x,ll w){f[x]+=w;g[x]+=w;s[x]+=w;}void P(int v){X[v]&&(PF(ls,X[v],Y[v]),PF(rs,X[v],Y[v]),X[v]=Y[v]=0);s[v]&&(PS(ls,s[v]),PS(rs,s[v]),s[v]=0);}
	void BD(int l=1,int r=n,int v=1){R[v]=r;L[v]=l;if(l==r) return;int m=l+r>>1;BD(l,m,ls);BD(m+1,r,rs);}void Up(int v){f[v]=f[rs];g[v]=g[ls];}
	void Ins(int x,ll y,int l=1,int r=n,int v=1){if(l==r) {f[v]=g[v]=y;return;}int m=l+r>>1;P(v);x<=m?Ins(x,y,l,m,ls):Ins(x,y,m+1,r,rs);Up(v);}
	ll Qry(int x,int l=1,int r=n,int v=1){if(l==r) return f[v];P(v);int m=l+r>>1;return x<=m?Qry(x,l,m,ls):Qry(x,m+1,r,rs);}
	void Add(int x,int y,ll A,ll B,int l=1,int r=n,int v=1){if(x<=l&&r<=y&&f[v]<=A*r+B) return;if(x<=l&&r<=y&&g[v]>=A*l+B) return PF(v,A,B);int m=l+r>>1;P(v);x<=m&&(Add(x,y,A,B,l,m,ls),0);y>m&&(Add(x,y,A,B,m+1,r,rs),0);Up(v);}
	void Mdf(int x,int y,ll z,int l=1,int r=n,int v=1){if(x<=l&&r<=y) return PS(v,z);int m=l+r>>1;P(v);x<=m&&(Mdf(x,y,z,l,m,ls),0);y>m&&(Mdf(x,y,z,m+1,r,rs),0);Up(v);}
	#undef ls
	#undef rs 
}
void dfs(int x){Fr[x]=En[x]=x;
	L[x]&&(dfs(L[x]),Fr[x]=Fr[L[x]]);R[x]&&(dfs(R[x]),En[x]=En[R[x]]);for(int i:S[x]) Ans[i]=min(T2::Qry(X[i])+1ll*A[x]*(Y[i]-x+1),T1::Qry(Y[i])+1ll*A[x]*(x-X[i]+1));
	ll P1,P2;T2::Ins(x,P2=(R[x]?T2::Qry(x+1):0)+A[x]);T1::Ins(x,P1=(L[x]?T1::Qry(x-1):0)+A[x]);Fr[x]^x&&(T2::Add(Fr[x],x-1,-A[x],P2+1ll*A[x]*x-1ll*(En[x]-x+1)*A[x]),T2::Mdf(Fr[x],x-1,1ll*(En[x]-x+1)*A[x]),0);En[x]^x&&(T1::Add(x+1,En[x],A[x],P1-1ll*A[x]*x-1ll*(x-Fr[x]+1)*A[x]),T1::Mdf(x+1,En[x],1ll*(x-Fr[x]+1)*A[x]),0);
	//for(int i=x-1;i>=Fr[x];i--) f[i]=min(f[i]+1ll*(En[x]-x+1)*A[x],f[x]+1ll*(x-i)*A[x]);for(int i=x+1;i<=En[x];i++) g[i]=min(g[i]+1ll*(x-Fr[x]+1)*A[x],g[x]+1ll*(i-x)*A[x]); 
}
vector<ll> minimum_costs(vector<int> Hs,vector<int> Xs,vector<int> Ys){
	n=Hs.size();m=Xs.size();int i,j;A[0]=INF;for(i=1;i<=n;i++){A[i]=Hs[i-1];while(A[i]>A[st[H]]) H--;L[i]=R[st[H]];R[st[H]]=i;st[++H]=i;}for(i=2;i<=n;i++) lg[i]=lg[i/2]+1;T1::BD();T2::BD();Make(R[0],0);
	for(i=1;i<=m;i++) X[i]=Xs[i-1]+1,Y[i]=Ys[i-1]+1,S[LCA(X[i],Y[i])].PB(i);dfs(R[0]);vector<ll> ToT;ToT.clear();for(i=1;i<=m;i++) ToT.push_back(Ans[i]);return ToT;
}
posted @ 2022-08-28 18:45  275307894a  阅读(14)  评论(0编辑  收藏  举报
浏览器标题切换
浏览器标题切换end