题意:给一棵树每条边有a,b两个值,给你一个m,表示从0到m-1,假设当前为i,那么每条边的权值是a*i+b,求该树任意两点的最大权值

题解:首先我们需要维护出(a,b)的凸壳,对于每个i在上面三分即可,点对用树分治维护,假设当前重心是u,那么把u的直接儿子挨个合并凸壳,这一过程用闵可夫斯基和维护,set启发式合并.

//#pragma GCC optimize(2)
//#pragma GCC optimize(3)
//#pragma GCC optimize(4)
//#pragma GCC optimize("unroll-loops")
//#pragma comment(linker, "/stack:200000000")
//#pragma GCC optimize("Ofast,no-stack-protector")
//#pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
#include<bits/stdc++.h>
#define fi first
#define se second
#define db double
#define mp make_pair
#define pb push_back
#define pi acos(-1.0)
#define ll long long
#define vi vector<int>
#define mod 1000000007
#define ld long double
//#define C 0.5772156649
//#define ls l,m,rt<<1
//#define rs m+1,r,rt<<1|1
#define pll pair<ll,ll>
#define pil pair<int,ll>
#define pli pair<ll,int>
#define pii pair<int,int>
#define ull unsigned long long
//#define base 1000000000000000000
#define fin freopen("a.txt","r",stdin)
#define fout freopen("a.txt","w",stdout)
#define fio ios::sync_with_stdio(false);cin.tie(0)
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline void sub(ll &a,ll b){a-=b;if(a<0)a+=mod;}
inline void add(ll &a,ll b){a+=b;if(a>=mod)a-=mod;}
template<typename T>inline T const& MAX(T const &a,T const &b){return a>b?a:b;}
template<typename T>inline T const& MIN(T const &a,T const &b){return a<b?a:b;}
inline ll qp(ll a,ll b){ll ans=1;while(b){if(b&1)ans=ans*a%mod;a=a*a%mod,b>>=1;}return ans;}
inline ll qp(ll a,ll b,ll c){ll ans=1;while(b){if(b&1)ans=ans*a%c;a=a*a%c,b>>=1;}return ans;} using namespace std; const ull ba=233;
const db eps=1e-5;
const ll INF=0x3f3f3f3f3f3f3f3f;
const int N=100000+10,maxn=100000+10,inf=0x3f3f3f3f; struct FastIO {
static const int S = 1e7;
int wpos;
char wbuf[S];
FastIO() : wpos(0) {}
inline int xchar() {
static char buf[S];
static int len = 0, pos = 0;
if (pos == len)
pos = 0, len = fread(buf, 1, S, stdin);
if (pos == len) exit(0);
return buf[pos++];
}
inline int xuint() {
int c = xchar(), x = 0;
while (c <= 32) c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x;
}
inline int xint()
{
int s = 1, c = xchar(), x = 0;
while (c <= 32) c = xchar();
if (c == '-') s = -1, c = xchar();
for (; '0' <= c && c <= '9'; c = xchar()) x = x * 10 + c - '0';
return x * s;
}
inline void xstring(char *s)
{
int c = xchar();
while (c <= 32) c = xchar();
for (; c > 32; c = xchar()) * s++ = c;
*s = 0;
}
inline void wchar(int x)
{
if (wpos == S) fwrite(wbuf, 1, S, stdout), wpos = 0;
wbuf[wpos++] = x;
}
inline void wint(ll x)
{
if (x < 0) wchar('-'), x = -x;
char s[24];
int n = 0;
while (x || !n) s[n++] = '0' + x % 10, x /= 10;
while (n--) wchar(s[n]);
wchar('\n');
}
inline void wstring(const char *s)
{
while (*s) wchar(*s++);
}
~FastIO()
{
if (wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
}
} io;
struct edge{int to,Next,a,b;}e[maxn<<1];
int cnt,head[N],sz[N],zx[N],n;
pll dis[N];
bool vis[N];
void init(){cnt=0;memset(head,-1,sizeof head);memset(vis,0,sizeof vis);}
void add(int u,int v,int a,int b){e[cnt].to=v;e[cnt].a=a;e[cnt].b=b;e[cnt].Next=head[u];head[u]=cnt++;}
void dfssz(int u,int f,int &sum)
{
sum++;sz[u]=1;
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dfssz(x,u,sum);sz[u]+=sz[x];
}
}
void dfszx(int u,int f,int sum,int &ans,int &id)
{
zx[u]=sum-sz[u];
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
dfszx(x,u,sum,ans,id);
zx[u]=max(zx[u],sz[x]);
}
if(ans>zx[u]){ans=zx[u],id=u;}
}
int findzx(int root)
{
int sum=0;
dfssz(root,-1,sum);
int ans=inf,id=0;
dfszx(root,-1,sum,ans,id);
return id;
} struct Point {
ll x, y;
Point(ll x = 0, ll y = 0) : x(x), y(y) {}
};
typedef Point Vector;
Point operator + (Vector A, Vector B) {return Point(A.x + B.x, A.y + B.y);}
Point operator - (Vector A, Vector B) {return Point(A.x - B.x, A.y - B.y);}
bool operator == (const Vector &A, const Point &B) {return A.x == B.x&& A.y == B.y;}
bool operator < (const Vector &A, const Vector &B) {return A.y < B.y || (A.y == B.y && A.x < B.x);}
ll Cross(Vector A, Vector B) {return A.x * B.y - A.y * B.x;}
int ConvexHull(Point *p, int n, Point *ch) {
sort(p, p + n);
int m = 0;
for(int i = 0; i < n; i++) {
while(m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m--;
ch[m++] = p[i];
}
int k = m;
for(int i = n - 2; i >= 0; i--) {
while(m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m--;
ch[m++] = p[i];
}
return n==1?m:m - 1;
}
int minkowski(Point *a,int &n,Point *b,int &m,Point *c,Point *d)
{
int top=0;
if(n<=2||m<=2)
{
for(int i=0;i<n;i++)for(int j=0;j<m;j++)
d[top++]=a[i]+b[j];
top=ConvexHull(d,top,c);
return top;
}
c[top++]=a[0]+b[0];
for(int i=0,j=0;i<n||j<m;)
{
Point p1=a[i%n]+b[(j+1)%m],p2=a[(i+1)%n]+b[j%m];
if(Cross(p1-c[top-1],p2-c[top-1])>=0)c[top++]=p1,++j;
else c[top++]=p2,++i;
}
return top-1;
}
Point a[N*40],b[N],c[N*4],d[N*4],ans[N*40];
vector<Point>v[N];
int top,la,lb;
void dfsdis(int u,int f,int root)
{
int num=0;
for(int i=head[u];~i;i=e[i].Next)
{
int x=e[i].to;
if(x==f||vis[x])continue;
num++;
dis[x].fi=dis[u].fi+e[i].a;
dis[x].se=dis[u].se+e[i].b;
dfsdis(x,u,root);
}
if(num==0)v[root].pb({dis[u].fi,dis[u].se});
}
void gao(int x)
{
la=0;
for(int i=0;i<v[x].size();i++)a[la++]=v[x][i];
lb=ConvexHull(a,la,b);v[x].clear();
for(int i=0;i<lb;i++)v[x].pb(b[i]);
}
void solve(int root)
{
int p=findzx(root);
v[0].clear();v[0].pb({0,0});
set<pii>s;s.clear();s.insert(mp(v[0].size(),0));
for(int i=head[p];~i;i=e[i].Next)
{
int x=e[i].to;if(vis[x])continue;
v[x].clear();
dis[x]=mp(e[i].a,e[i].b);dfsdis(x,p,x);
gao(x);s.insert(mp(v[x].size(),x));
}
while(s.size()>=2)
{
int x=s.begin()->se;s.erase(s.begin());
int y=s.begin()->se;s.erase(s.begin());
la=lb=0;
for(int i=0;i<v[x].size();i++)a[la++]=v[x][i];
for(int i=0;i<v[y].size();i++)b[lb++]=v[y][i];
int te=minkowski(a,la,b,lb,c,d);
for(int i=0;i<te;i++)ans[top++]=c[i];
for(int i=0;i<v[y].size();i++)v[x].pb(v[y][i]);v[y].clear();
gao(x);s.insert(mp(v[x].size(),x));
}
vis[p]=1;
for(int i=head[p];~i;i=e[i].Next)
{
int x=e[i].to;
if(vis[x])continue;
solve(e[i].to);
}
}
int main()
{
int n=io.xint(),m=io.xint();
init();
for(int i=1;i<n;i++)
{
int u=io.xint(),v=io.xint(),a=io.xint(),b=io.xint();
add(u,v,a,b);add(v,u,a,b);
}
solve(1);
top=ConvexHull(ans,top,a);
for(int i=0;i<m;i++)
{
int l=-1,r=top;
while(l<r-6)
{
int m=(l+r)>>1,m1=(m+r)>>1;
if(a[m].x*i+a[m].y>a[m1].x*i+a[m1].y)r=m1;
else l=m;
}
ll ma=0;
for(int j=max(0,l-10);j<min(top,l+10);j++)ma=max(ma,a[j].x*i+a[j].y);
io.wint(ma);
}
return 0;
}
/******************** ********************/

最新文章

  1. ASP.NET MVC5下载数据到Excel文件
  2. callback 转换到 promise
  3. Xcode中创建文件夹
  4. 5.python(迭代器,装饰器,生成器,基本算法,正则)
  5. c 指针(一)
  6. 【转】ExcelHelper类,用npoi读取Excel文档
  7. Using innodb_large_prefix to avoid ERROR #1071,Specified key was too long; max key length is 1000 bytes
  8. Response对象
  9. 减少iOS应用程序安装包大小
  10. IOS优秀博客
  11. mysql重装后出现乱码解决办法
  12. jQuery Mobile 学习
  13. Adobe Photoshop安装
  14. android 短信拦截
  15. 【web前端】移动端控制台插件,手机端页面查看相关页面控制台信息
  16. sqrt函数的实现
  17. [zhuan]《MEF程序设计指南》博文汇总
  18. Sphinx以及coreseek的安装及使用
  19. # WinForm关闭窗体确认
  20. pygame学习笔记(5)——精灵

热门文章

  1. JPA原理与实践、多数据源配置
  2. Spring Boot以War包启动
  3. JVM相关笔记
  4. 洛谷P1164 小A点菜 DP入门
  5. idea 常用设置初始化
  6. Use Memory Layout from Target Dialog Scatter File
  7. 5、iptables之nat
  8. 理解ffmpeg中的pts,dts,time_base
  9. PL/SQL Developer过期解决方法
  10. 【UOJ】#273. 【清华集训2016】你的生命已如风中残烛