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

n≤2×105n\leq 2\times 10^5n≤2×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;
}

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

  1. [洛谷P4721]【模板】分治 FFT

    题目大意:给定长度为$n-1$的数组$g_{[1,n)}$,求$f_{[0,n)}$,要求: $$ f_i=\sum_{j=1}^if_{i-j}g_j\\ f_0=1 $$ 题解:直接求复杂度是$O ...

  2. 洛谷 - P4721 【模板】分治 FFT(分治NTT)

    题目链接:点击查看 题目大意:给出序列 g1,⋯,ng_{1,\cdots,n}g1,⋯,n​,求 f0,⋯,nf_{0,\cdots,n}f0,⋯,n​ 规定 fi=∑j=1ifi−jgjf_i=\ ...

  3. 洛谷P4233 射命丸文的笔记 分治NTT+竞赛图

    Description 给定n 对于i从1~n,输出i个点组成竞赛图中,哈密顿回路的平均数量 Solution 竞赛图存在哈密顿回路的充要条件就是强连通 设f(n)f(n)f(n)表示n个点形成强连通 ...

  4. [洛谷P1498] 南蛮图腾(分治+递归)

    分析 根据题目标签,首先解释一下分治算法:分治算法的基本思想是将一个规模为N的问题分解为K个规模较小的子问题,这些子问题相互独立且与原问题性质相同.求出子问题的解,就可得到原问题的解.即一种分目标完成 ...

  5. 洛谷P1966 火柴排队(cdq分治 + 逆序对)

    2020.6.8 练二分了当然要练练分治,这些基础的处理手段真的还是蛮好用的. 这道题是问ai 和bi的平方和最小,最少需要的相邻的交换次数.手动模拟了一下感觉没什么思路.但是后来注意到每次只能移动相 ...

  6. Bzoj4016/洛谷P2993 [FJOI2014] 最短路径树问题(最短路径问题+长链剖分/点分治)

    题面 Bzoj 洛谷 题解 首先把最短路径树建出来(用\(Dijkstra\),没试过\(SPFA\)\(\leftarrow\)它死了),然后问题就变成了一个关于深度的问题,可以用长链剖分做,所以我 ...

  7. 分治——Secret Cow Code S(洛谷 P3612)

    题目选自洛谷P3612 梳理题意 给定一个字符串,每次将其最后一个字符移到最前方,形成的新串接到原串后作为下一次操作的字符串 现询问第 N 个位置的字符 简要分析 看一眼数据范围,N<10^18 ...

  8. 分治——南蛮图腾(洛谷 P1498)

    题目选自洛谷P1498 把杨辉三角对2取模输出看下结果,这是12行内的结果: 11 1 1 0 1 1 1 1 1 1 0 0 0 1 1 1 0 0 1 1 1 0 1 0 1 0 1 1 1 1 ...

  9. BZOJ4553/洛谷P4093 [HEOI2016/TJOI2016]序列 动态规划 分治

    原文链接http://www.cnblogs.com/zhouzhendong/p/8672434.html 题目传送门 - BZOJ4553 题目传送门 - 洛谷P4093 题解 设$Li$表示第$ ...

最新文章

  1. android activity之间传值
  2. python爬取方式_Python 爬虫入门(三)—— 寻找合适的爬取策略
  3. python云端系统开发入门_Python云端系统开发入门
  4. MIUI(Android)使用Webview上传文件
  5. Windows Phone 7调用必应翻译服务
  6. java520.1314表白_520表白套路对话大全 表白算式521.1314大全
  7. 3D打印行业入行总结
  8. 英语对于软件开发者来说到底有多重要?
  9. 苹果开发者账号申请教程
  10. 虚拟主机共享IP地址
  11. php 有下划线的方法,编码风格 - PHP类方法中领先的下划线有什么用?
  12. 计算机在语文教学中,计算机技术在语文教学中的运用
  13. 任意进制转换为十进制(十六进制转换为十进制)
  14. Solved: ERROR: Failed building wheel for hdbscan
  15. VS:如何解决VS2015的30天试用期已过即VS2015许可证已过期的问题
  16. Vivado与modelsim联合仿真(2018.3---10.6c)
  17. SUST暑期集训题解(可持久化数据结构)
  18. 收藏上全募金资模式及策略
  19. 网络新闻评论观点挖掘系统实现
  20. 将虚拟机的Ubuntu映射为windows的网络驱动器

热门文章

  1. 语言 ota_荣威RX5 PLUS使用最新的家族设计语言,给人更年轻时尚的感觉
  2. 如果边横向移动边扔球,球会怎么运动?
  3. 已婚男人看见美女都这个眼神?
  4. 哪个男孩不想拥有这种牌面?
  5. 盘点那些世间顶级直男hhhhhh | 今日最佳
  6. php输出PDF的文件流_怎么用PHP在HTML中生成PDF文件
  7. java spark读写hdfs_Spark读取HDFS数据输出到不同的文件
  8. python中csv文件把成绩加入_【学习笔记】python3中csv文件使用
  9. python插入排序_python 插入排序,选择排序
  10. 安装默认报表服务器虚拟目录,本机模式安装默认配置 (Reporting Services)