洛谷P5114 八月脸(边分治+闵可夫斯基和)

传送门
边分治+闵可夫斯基和即可(注意要处理lca的情况
简单易懂,我们赢了(滑稽保命
代码:

#include<bits/stdc++.h>
#define ri register int
#define fi first
#define se second
using namespace std;
const int rlen=1<<18|1;
inline char gc(){
	static char buf[rlen],*ib,*ob;
	(ib==ob)&&(ob=(ib=buf)+fread(buf,1,rlen,stdin));
	return ib==ob?-1:*ib++;
}
inline int read(){
	int ans=0;
	bool f=1;
	char ch=gc();
	while(!isdigit(ch))f^=ch=='-',ch=gc();
	while(isdigit(ch))ans=((ans<<2)+ans<<1)+(ch^48),ch=gc();
	return f?ans:-ans;
}
typedef long long ll;
typedef pair<int,int> pii;
const int N=5e5+5,inf=0x3f3f3f3f;
vector<int>g[N],Son[N],e[N];
int va[N],vb[N],typ[N],n,m,qr,siz[N],all,Fa[N],ft[N];
pii Rt;
struct pot{
	ll x,y;
	pot(ll x=0,ll y=0):x(x),y(y){}
	friend inline pot operator+(const pot&a,const pot&b){return pot(a.x+b.x,a.y+b.y);}
	friend inline pot operator-(const pot&a,const pot&b){return pot(a.x-b.x,a.y-b.y);}
	friend inline ll operator^(const pot&a,const pot&b){return a.x*b.y-a.y*b.x;}
    friend inline bool operator<(const pot&a,const pot&b){return a.x^b.x?a.x<b.x:a.y<b.y;}
};
vector<pot>ptt,pt[2][2];
bool vis[N];
inline void graham(vector<pot>&a){
	static int top=0,q[N],n;
	top=0,n=a.size()-1;
    sort(a.begin(),a.end());
	for(ri i=0;i<=n;++i){
		while(top>1&&((a[i]-a[q[top]])^(a[q[top]]-a[q[top-1]]))<=0)--top;
		q[++top]=i;
	}
	for(ri i=1;i<=top;++i)a[i-1]=a[q[i]];
	a.resize(top);
}
inline void Msum(vector<pot>a,vector<pot>b){
    if(!a.size()||!b.size())return;
	graham(a),graham(b);
	ptt.push_back(a[0]+b[0]);
	int n=a.size()-1,m=b.size()-1,p1=0,p2=0;
	pot ta,tb;
	while(p1<n&&p2<m){
		ta=a[p1+1]-a[p1],tb=b[p2+1]-b[p2];
		if((ta^tb)<=0)ptt.push_back(ptt.back()+ta),++p1;
		else ptt.push_back(ptt.back()+tb),++p2;
	}
	while(p1<n)ptt.push_back(ptt.back()+a[p1+1]-a[p1]),++p1;
	while(p2<m)ptt.push_back(ptt.back()+b[p2+1]-b[p2]),++p2;
}
void dfs(int p,int fa){
	for(ri i=0,v;i<g[p].size();++i){
		if((v=g[p][i])==fa)continue;
		dfs(v,p),Son[p].push_back(v);
	}
}
bool chs[N];
void dfs1(int p,int fa,int sz){
	siz[p]=1;
	for(ri t,i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||vis[v])continue;
		dfs1(v,p,sz),siz[p]+=siz[v];
		if((t=max(siz[v],sz-siz[v]))<all)all=t,Rt=pii(p,v);
	}
}
void dfs2(int p,int fa,pot dis,int op){
	bool ff=chs[ft[p]];
	if(!ff)chs[ft[p]]=1,dis=dis+pot(va[ft[p]],vb[ft[p]]);
	if(~typ[p])pt[op][typ[p]].push_back(dis);
	for(ri i=0,v;i<e[p].size();++i){
		if((v=e[p][i])==fa||vis[v])continue;
		dfs2(v,p,dis,op);
	}
	chs[ft[p]]=ff;
}
void Dfs(int p,int sz){
	all=inf;
	dfs1(p,0,sz);
	if(all==inf)return;
	int a=Rt.fi,b=Rt.se;
	for(ri i=0;i<2;++i)for(ri j=0;j<2;++j)pt[i][j].clear();
    if(Fa[a]==b){
		chs[ft[b]]=1;
        dfs2(a,b,pot(0,0),0);
        dfs2(b,a,pot(va[ft[b]],vb[ft[b]]),1);
		chs[ft[b]]=0;
    }
    else{
		chs[ft[a]]=1;
        dfs2(b,a,pot(0,0),1);
		dfs2(a,b,pot(va[ft[a]],vb[ft[a]]),0);
		chs[ft[a]]=0;
    }
    Msum(pt[0][0],pt[1][1]),Msum(pt[0][1],pt[1][0]);
	vis[b]=1,Dfs(a,sz-siz[b]),vis[b]=0;
	vis[a]=1,Dfs(b,siz[b]),vis[a]=0;
}
void rebuild(){
	for(ri v1,v2,i=1,up;i<=m;++i){
		up=Son[i].size();
		if(up<3){
			for(ri j=0;j<up;++j){
				e[i].push_back(Son[i][j]);
				e[Son[i][j]].push_back(i);
                Fa[Son[i][j]]=i;
			}
		}
		else{
			typ[v1=++m]=-1;
			e[i].push_back(v1),e[v1].push_back(i);
            Fa[v1]=i,ft[v1]=ft[i];
			typ[v2=++m]=-1;
			e[i].push_back(v2),e[v2].push_back(i);
            Fa[v2]=i,ft[v2]=ft[i];
			for(ri j=0;j<up;++j)Son[j&1?v1:v2].push_back(Son[i][j]);
		}
	}
}
inline ll query(int k){
	int n=ptt.size()-1;
	ll ret=-1e18;
	pot t=pot(-1,k);
	if(ptt.size()<=10){
		for(ri i=0;i<=n;++i)ret=max(ret,(ptt[i]^t));
		return ret;
	}
	if(((ptt[1]-ptt[0])^t)<=0)return ptt[0]^t;
	if(((ptt[n]-ptt[n-1])^t)>=0)return ptt[n]^t;
	int L=1,R=n-1;
	while(L<=R){
		int mid=(L+R)>>1;
		bool f1=((ptt[mid+1]-ptt[mid])^t)<=0,f2=((ptt[mid]-ptt[mid-1])^t)<=0;
		if(f1^f2)return ptt[mid]^t;
		if(f1&&f2)R=mid-1;
		else L=mid+1;
	}
}
int main(){
	#ifdef ldxcaicai
	freopen("lx.in","r",stdin);
    freopen("lx.out","w",stdout);
	#endif
	n=m=read(),qr=read();
	for(ri i=1;i<=n;++i)va[i]=read();
	for(ri i=1;i<=n;++i)vb[i]=read();
	for(ri i=1;i<=n;++i)typ[i]=read(),ft[i]=i;
	for(ri i=1,u,v;i<n;++i){
		u=read(),v=read();
		g[u].push_back(v);
		g[v].push_back(u);
	}
	dfs(1,0);
	rebuild();
    Dfs(1,m);
	graham(ptt);
	while(qr--)cout<<query(read())<<'\n';
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值