【洛谷P5114】八月脸【边分治】【闵可夫斯基和】

题意:一棵 nnn 个点的树,每个点有两个权值 ai,bia_i,b_iai,bi,有黑白两种颜色。mmm 次询问,每次给定一个 kkk,求一条端点异色的路径,使得 k∑ai+∑bik\sum a_i+\sum b_ikai+bi 最大化。

n≤2×105n\leq 2\times 10^5n2×105

就差把“请在边分治的时候维护闵可夫斯基和”写题面上了……

直观来看是把 (ai,bi)(a_i,b_i)(ai,bi) 看成直线,但是并不好维护。不过半平面交和凸包是对偶的,并且凸包合并有闵可夫斯基和这个东西,所以可以把每个结点直接看成点维护凸包,询问的时候二分就可以了。

分治的时候对两边黑白分别求出凸壳,然后交叉合并,把点丢到答案集合里最后再做一个凸包就可以了。

然后就是三度化后处理答案的问题。把新建的虚点的参数从父亲那里复制,然后如果路径的 lca 是虚点强行给它加上去。可以在 dfs 的时候记一个当前走的方向,然后如果是往上走的可以进行一次换方向,并在这里统计当前点是否需要有贡献。

复杂度 O(nlog⁡n)\Omicron(n\log n)O(nlogn)

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cctype>
#include <vector>
#include <algorithm>
#define MAXN 200005
#define MAXM 400005
using namespace std;
const int INF=0x7fffffff;
inline int read()
{int ans=0,f=1;char c=getchar();while (!isdigit(c)) (c=='-')&&(f=-1),c=getchar();while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar();return f*ans;
}
typedef long long ll;
struct point{int x,y;inline point(const int& x=0,const int& y=0):x(x),y(y){}};
inline point operator +(const point& a,const point& b){return point(a.x+b.x,a.y+b.y);}
inline point operator -(const point& a,const point& b){return point(a.x-b.x,a.y-b.y);}
inline ll operator *(const point& a,const point& b){return (ll)a.x*b.y-(ll)a.y*b.x;}
inline bool operator <(const point& a,const point& b){return a.x<b.x||(a.x==b.x&&a.y>b.y);}
typedef vector<point> hull;
#define s(t) ((int)(t).size())
void make_hull(hull& A)
{hull t;sort(A.begin(),A.end());for (int i=0;i<(int)A.size();i++){if (i&&A[i].x==A[i-1].x) continue;while (s(t)>1&&(t[s(t)-1]-t[s(t)-2])*(A[i]-t[s(t)-1])>0) t.pop_back();t.push_back(A[i]);}A=t;
}
void merge(const hull& A,const hull& B,hull& C)
{if (A.empty()||B.empty()) return;int i,j;hull ans;for (i=j=0;i<s(A)-1&&j<s(B)-1;){if ((A[i+1]-A[i])*(B[j+1]-B[j])>0) ans.push_back(B[j+1]-B[j]),++j;else ans.push_back(A[i+1]-A[i]),++i;}while (i<s(A)-1) ans.push_back(A[i+1]-A[i]),++i;while (j<s(B)-1) ans.push_back(B[j+1]-B[j]),++j;point las=A[0]+B[0];C.push_back(las);for (int i=0;i<s(ans);i++) C.push_back(las=las+ans[i]);
}
vector<int> E[MAXN];
struct edge{int u,v;}e[MAXM];
int head[MAXN],nxt[MAXM],cnt=1;
inline void addnode(int u,int v)
{e[++cnt]=(edge){u,v};nxt[cnt]=head[u];head[u]=cnt;
}
point val[MAXN];
int vis[MAXN],dep[MAXN],type[MAXN],n,tot;
void dfs(int u)
{vis[u]=1;if ((int)E[u].size()<=3){for (int i=0;i<(int)E[u].size();i++)if (!vis[E[u][i]])dep[E[u][i]]=dep[u]+1,dfs(E[u][i]),addnode(u,E[u][i]),addnode(E[u][i],u);	return;			}int cur[2]={++tot,++tot},pos=0;addnode(u,cur[0]),addnode(cur[0],u);addnode(u,cur[1]),addnode(cur[1],u);val[cur[0]]=val[cur[1]]=val[u];type[cur[0]]=type[cur[1]]=type[u];dep[cur[0]]=dep[cur[1]]=dep[u]+1;for (int i=0;i<(int)E[u].size();i++)if (!vis[E[u][i]])E[cur[pos^=1]].push_back(E[u][i]);dfs(cur[0]),dfs(cur[1]);
}
int tp;
int rt,mn,siz[MAXN];
void findrt(int u,int f,int sum)
{siz[u]=1;for (int i=head[u];i;i=nxt[i])if (!vis[i>>1]&&e[i].v!=f){findrt(e[i].v,u,sum);if (max(siz[e[i].v],sum-siz[e[i].v])<mn) mn=max(siz[e[i].v],sum-siz[e[i].v]),rt=i;siz[u]+=siz[e[i].v];}
}
hull A[2],B[2],lis;
void dfs(int u,int f,point cur,hull* A,bool up)
{if (u<=n) A[type[u]].push_back(cur=cur+val[u]);for (int i=head[u];i;i=nxt[i])if (!vis[i>>1]&&e[i].v!=f&&(up^(dep[e[i].v]>dep[u])))dfs(e[i].v,u,cur,A,up);if (up){if (u>n) A[type[u]].push_back(cur=cur+val[u]);for (int i=head[u];i;i=nxt[i])if (!vis[i>>1]&&e[i].v!=f&&dep[e[i].v]>dep[u])dfs(e[i].v,u,cur,A,0);}
}
void calc()
{A[0].clear(),A[1].clear();B[0].clear(),B[1].clear();int u=e[rt].u,v=e[rt].v;if (dep[u]>dep[v]) swap(u,v);dfs(v,0,point(0,0),A,0);dfs(u,0,point(0,0),B,1);make_hull(A[0]),make_hull(A[1]);make_hull(B[0]),make_hull(B[1]);merge(A[0],B[1],lis);merge(A[1],B[0],lis);
}
void solve(int sum)
{if (mn==INF) return;vis[rt>>1]=1;calc();int cur=rt,sz=siz[e[rt].v];mn=INF,findrt(e[cur].v,0,sz),solve(sz);mn=INF,findrt(e[cur].u,0,sum-sz),solve(sum-sz);
}
int main()
{tot=n=read();int m=read();for (int i=1;i<=n;i++) val[i].x=read();for (int i=1;i<=n;i++) val[i].y=read();for (int i=1;i<=n;i++) type[i]=read();for (int i=1;i<n;i++){int u,v;u=read(),v=read();E[u].push_back(v),E[v].push_back(u);}dep[1]=1,dfs(1);memset(vis,0,sizeof(vis));mn=INF,findrt(1,0,tot),solve(tot);make_hull(lis);
//	for (int i=0;i<(int)lis.size();i++) printf("%d %d\n",lis[i].x,lis[i].y);lis.push_back(point(lis.back().x,-INF));while (m--){int k=read();int l=0,r=s(lis)-2,mid;while (l<r){mid=(l+r)>>1;if (point(1,-k)*(lis[mid+1]-lis[mid])>0) l=mid+1;else r=mid;}printf("%lld\n",(ll)k*lis[l].x+lis[l].y);}return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/314831.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Educational Codeforces Round 75 (Rated for Div. 2) E2. Voting (Hard Version) 贪心

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; n≤2e5,m≤n,p≤1e9n\le2e5,m\le n,p\le 1e9n≤2e5,m≤n,p≤1e9 思路&#xff1a; 首先需要发现一些性质&#xff0c;假设preipre_iprei​代表所有mj<im_j< imj​<i的pjp_jpj​和。可以发现&#…

【招聘(深圳)】敢为软件技术有限公司 .Net 工程师

敢为软件介绍&#xff1a;深圳市敢为软件技术有限公司致力于打造面向未来的最酷最具影响力的高科技公司。敢为软件在万物互联、行业应用、大屏可视化及自然交互等方面形成完整的闭环&#xff0c;是物联网领域连接能力最强、应用领域最广、用户体验最好的高科技公司。在万物互联…

【WC2018】通道【边分治】【虚树】【树的直径】

题意&#xff1a;给三棵基于同一点集的带边权的树&#xff0c;边权非负&#xff0c;求两点间三棵树上距离之和的最大值。 n≤105n\leq 10^5n≤105 一句话题解&#xff1a;在第一棵树上做边分治&#xff0c;丢到第二棵树上建虚树&#xff0c;在虚树上根据第三棵树的直径dp。 首…

DevOps案例研究:知人善任——Google敏捷核心文化

内容来源&#xff1a;DevOps案例深度研究-Google敏捷实践战队&#xff0c;本文只展示部分PPT及研究成果&#xff0c;更多细节请关注案例分享会。本文内容贡献者&#xff1a;陈霁、刘翀、谈佳婧、张霖。阅读干货前先感受一下热烈的氛围~一、Google如何快速交付原型1.1 Savioke公…

Educational Codeforces Round 111 (Rated for Div. 2) E. Stringforces 二分 + 状压dp

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个串&#xff0c;只包含前kkk个字母和&#xff1f;&#xff1f;&#xff1f;&#xff0c;定义fif_ifi​表示第iii个字母在串中出现的最长连续长度&#xff0c;你现在需要将???替换为前kkk个字母&am…

MTT 学习笔记

很久以前就听说了这东西&#xff0c;一直没空学。最近重学多项式&#xff0c;就重新搞了一下。 MTT 主要解决的是任意模数&#xff08;或者说是没有模数&#xff09;的多项式乘法&#xff0c;可以用于应对专门恶心人的毒瘤题。 首先&#xff0c;假设多项式次数 10510^5105,值…

在 VS Code 中轻松 review GitHub Pull Requests

相信大家在平时工作或者自己的项目中&#xff0c;一定都有在 GitHub 上进行 Code Review 的经历。对于韩老师来说&#xff0c;不论是平时工作的项目&#xff0c;还是自己的业余项目&#xff0c;代码基本都是在 GitHub 上。所以&#xff0c;在 GitHub 上进行 Pull Requests 的 C…

Codeforces Round #732 (Div. 2) C. AquaMoon and Strange Sort 思维

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你nnn个数&#xff0c;每个数初始方向是向右&#xff0c;每次可以交换相邻两个位置并且将这两个位置的方向调换&#xff0c;问这个序列的最终状态能否是非递减且方向都向右。 n≤1e5,ai≤1e5n\le1e5,a_i\l…

【CC November Challenge 2012】Arithmetic Progressions【分块】【FFT】

题意&#xff1a;给定长度为 nnn 的正整数序列 AAA,求满足 i<j<k,Aj−AiAk−Aji<j<k,A_j-A_iA_k-A_ji<j<k,Aj​−Ai​Ak​−Aj​ 的三元组个数。 n≤105,Ai≤3104n\leq 10^5,A_i\leq 3\times 10^4n≤105,Ai​≤3104 三个位置只有 jjj 限制比较紧&#xff0c…

火热的云原生到底是什么?一文了解云原生四要素!

所谓云原生&#xff0c;它不是一个产品&#xff0c;而是一套技术体系和一套方法论&#xff0c;而数字化转型是思想先行&#xff0c;从内到外的整体变革。更确切地说&#xff0c;它是一种文化&#xff0c;更是一种潮流&#xff0c;是云计算的一个必然导向。随着虚拟化技术的成熟…

Codeforces Round #732 (Div. 2) D. AquaMoon and Chess 组合数学 + 找规律

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个010101串&#xff0c;当且仅当某个111的某一边i1,i−1i1,i-1i1,i−1有111&#xff0c;这个111可以跟i2,i−2i2,i-2i2,i−2交换位置&#xff0c;问最终能产生多少状态。 n≤1e5n\le1e5n≤1e5 思路&a…

为什么说拥抱.NET CORE的时候到了

微软和社区已经做了大量艰苦的工作&#xff0c;使.Net Core成为市场上具有竞争力的框架&#xff0c;帮助开发人员快速开发具有最佳性能和可扩展性的强大应用程序。做的最棒的事情是.Net Framework开发人员不需要任何新知识来处理.Net Core。这也是开发人员在很短的时间内采用.N…

【HNOI2016】序列【莫队】【单调栈】【ST表】

题意&#xff1a;给定序列 aia_iai​&#xff0c;qqq 次询问 [l,r][l,r][l,r] 所有子区间最小值之和。 n,q≤105n,q\leq 10^5n,q≤105 这种题一眼看上去是离线线段树&#xff0c;但这题每移动一位要维护区间取 min⁡\minmin&#xff0c;历史值之和&#xff0c;非常不可做。 所…

湖南大学第十六届程序设计竞赛 B Yuki with emofunc and playf 同余最短路

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 初始有一个数111&#xff0c;你每次可以将其∗10*10∗10或者(x−1)(x-1)(x−1)&#xff0c;现在给你xxx&#xff0c;问最少经过多少步能到达nnn。 1≤n≤1e6,1≤m≤1e91\le n\le1e6,1\le m\le1e91≤n≤1e6,1…

【HNOI2019】白兔之舞【组合数学】【矩阵快速幂】【单位根反演】【Chirp Z-Transform】【原根】【MTT】

题意&#xff1a;有一张 (L1)n(L1)\times n(L1)n 个点的有向图&#xff0c;每个结点有二元组 (x,y)(0≤x≤L,1≤y≤n)(x,y)~(0\leq x\leq L,1\leq y\leq n)(x,y) (0≤x≤L,1≤y≤n) 表示。对于所有 (u1,v1),(u2,v2)(u_1,v_1),(u_2,v_2)(u1​,v1​),(u2​,v2​)&#xff0c;若 u…

程序员如何学习英语

首先&#xff0c;这不是一篇广告&#xff0c;虽然这个标题很像。其次&#xff0c;我的英语水平也很一般&#xff0c;所以更多的是谈谈一些失败的经历和思考&#xff0c;俗话说&#xff0c;成功的经验不可复制&#xff0c;失败的经验倒可以让我们少走弯路。英语的重要性毋庸置疑…

Educational Codeforces Round 111 (Rated for Div. 2) D. Excellent Arrays 组合数学

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个数组aia_iai​&#xff0c;定义一个数组是好的当且仅当对于所有iii都有ai!ia_i!iai​!i。定义f(a)f(a)f(a)表示数组aaa中i<j,aiajiji<j,a_ia_jiji<j,ai​aj​ij的(i,j)(i,j)(i,j)对数。定义…

使用Azure云原生构建博客是怎样一种体验?(上篇)

点击上方蓝字关注“汪宇杰博客”导语https://edi.wang我的网站是在.NET Core 平台上使用 C#语言编写的开源博客系统&#xff0c;运行于微软智慧云 Azure 国际版上。本文将重点介绍 Azure 的各项服务如何为博客带来丝滑体验与保驾护航。历史回顾我博客的历史可以追溯到2003年&am…

AtCoder Regular Contest 100 D - Equal Cut 思维 + 前缀和

传送门 文章目录题意&#xff1a;思路&#xff1a;题意&#xff1a; 给你一个数组aaa&#xff0c;你要将其分成四份&#xff0c;让这四份中和的最大值−-−最小值最小&#xff0c;输出这个最小值。 n≤2e5,ai≤1e9n\le2e5,a_i\le1e9n≤2e5,ai​≤1e9 思路&#xff1a; 直接枚…

【UOJ574】多线程计算【二元二项式反演】【定积分】【矩阵】【NTT 卷积】

题意&#xff1a;有 nmn\times mnm 的网格&#xff0c;每个结点在 [0,1)[0,1)[0,1) 内的一个随机时刻被点亮。有 hhh 个数对 xi,yix_i,y_ixi​,yi​&#xff0c;对于一个瞬间状态&#xff0c;如果存在一个 xi,yix_i,y_ixi​,yi​ 使得恰好有 xix_ixi​ 行 yiy_iyi​ 列被点亮&a…