Code Chef TSUM2(动态凸包+点分治)
题面
题解
真是毒瘤随机化算法居然一分都不给
首先这种树上的题目一般想到的都是点分
我们考虑如何统计经过当前点的路径的贡献,设当前点\(u\)在序列中是第\(c\)个,那么一条路径的贡献就是
\]
其中前面是从子树到\(u\)的路径,后面是从\(u\)到子树里的路径
然后拆一下
\]
如果我们把这看成一条直线,形如\(y=kx+b\),其中\(k=c\),\(b=\sum_{i=1}^k i\times w_{p_i}\),那么这就是要求我们对于处理所有从\(u\)到子树的路径中,令\(x=\sum\limits_{i=c+1}^kw_{p_i}\)最大的\(y\)(因为对于一条固定的路径来说\(\sum\limits_{i=c+1}^k (i-c)w_{p_i}\)是个常数)
那么现在问题就变成了动态插入直线,动态维护最大值。可以李超线段树也可以动态凸包
不过因为路径是有序的,所以对于儿子需要正着跑一遍,倒着跑一遍
话说为啥我到了现在还会打错点分啊喂……
鉴于这玩意儿太难码了我代码直接抄zyy的了
//minamoto
#include<bits/stdc++.h>
#define R register
#define ll long long
#define inline __inline__ __attribute__((always_inline))
#define fp(i,a,b) for(R int i=(a),I=(b)+1;i<I;++i)
#define fd(i,a,b) for(R int i=(a),I=(b)-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
const int N=1e5+5;const ll inf=(1ll<<60);
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
bool qwq;
struct Line;typedef set<Line>::iterator IT;
struct Line{
ll k,b;mutable ll p;
inline Line(){}
inline Line(R ll kk,R ll bb,R ll pp):k(kk),b(bb),p(pp){}
inline bool operator <(const Line &b)const{return qwq?p<b.p:k<b.k;}
};
struct node{
multiset<Line>s;
bool inter(IT x,IT y){
if(y==s.end())return x->p=inf,0;
if(x->k==y->k)x->p=x->b>y->b?inf:-inf;
else x->p=(y->b-x->b)/(x->k-y->k);
return x->p>=y->p;
}
void ins(R ll k,R ll b){
IT it,z=s.insert(Line(k,b,0)),y=z++,x=y;
for(;inter(y,z);it=z,++z,s.erase(it));
if(x!=s.begin()&&inter(--x,y))it=y,++y,s.erase(it),inter(x,y);
for(;(y=x)!=s.begin()&&(--x)->p>=y->p;it=y,++y,s.erase(it),inter(x,y));
}
ll ask(R ll x){
qwq=1;IT res=s.lower_bound(Line(0,0,x));qwq=0;
return res==s.end()?-1e18:res->k*x+res->b;
}
};
int w[N],sz[N],mx[N],rt,size;ll res;bool vis[N];
int n;
void findrt(int u,int fa){
sz[u]=1,mx[u]=0;
go(u)if(!vis[v]&&v!=fa)findrt(v,u),sz[u]+=sz[v],cmax(mx[u],sz[v]);
cmax(mx[u],size-sz[u]);
if(mx[u]<mx[rt])rt=u;
}
void dfs1(int u,int fa,ll b,int d,ll x,node &s){
cmax(res,b+s.ask(x));
go(u)if(v!=fa&&!vis[v])dfs1(v,u,b+w[v]*(d+1),d+1,x+w[v],s);
}
void dfs2(int u,int fa,ll b,ll sum,int d,node &s){
s.ins(d,b);
go(u)if(v!=fa&&!vis[v])dfs2(v,u,b+sum+w[v],sum+w[v],d+1,s);
}
void solve(int u){
vis[u]=1;
static int st[N];int top=0;
node s1,s2;s1.ins(1,w[u]);
go(u)if(!vis[v]){
st[++top]=v;
dfs1(v,u,w[v],1,w[v],s1);
dfs2(v,u,w[v]+(w[u]<<1),w[v]+w[u],2,s1);
}
for(R int i=top,v;i&&(v=st[i]);--i){
dfs1(v,u,w[v],1,w[v],s2);
dfs2(v,u,w[v]+(w[u]<<1),w[v]+w[u],2,s2);
}
cmax(res,s2.ask(0)),cmax(res,1ll*w[u]);
int s=size;
go(u)if(!vis[v]){
rt=0,size=sz[v]>sz[u]?s-sz[u]:sz[v],findrt(v,0);
solve(rt);
}
}
int main(){
// freopen("testdata.in","r",stdin);
for(int T=read();T;--T){
n=read(),res=-inf;
fp(i,1,n)w[i]=read();
for(R int i=1,u,v;i<n;++i)u=read(),v=read(),add(u,v),add(v,u);
mx[0]=n+1,rt=0,size=n,findrt(1,0),solve(rt);
printf("%lld\n",res);
memset(head,0,(n+1)<<2);
memset(vis,0,n+1);
tot=0;
}
return 0;
}
Code Chef TSUM2(动态凸包+点分治)的更多相关文章
- Code Chef GEOCHEAT(凸包+旋转卡壳+随机化)
题面 传送门 题解 以下记\(S_i=\{1,2,3,...,i\}\) 我们先用凸包+旋转卡壳求出直径的长度,并记直径的两个端点为\(i,j\)(如果有多条直径随机取两个端点) 因为这个序列被\(r ...
- 【BZOJ 1701】Cow School(斜率优化/动态凸包/分治优化)
原题题解和数据下载 Usaco2007 Jan 题意 小牛参加了n个测试,第i个测试满分是\(p_i\),它的得分是\(t_i\).老师去掉\(t_i/p_i\)最小的d个测试,将剩下的总得分/总满分 ...
- 【BZOJ1492】【Luogu P4027】 [NOI2007]货币兑换 CDQ分治,平衡树,动态凸包
斜率在转移顺序下不满足单调性的斜率优化\(DP\),用动态凸包来维护.送命题. 简化版题意:每次在凸包上插入一个点,以及求一条斜率为\(K\)的直线与当前凸包的交点.思路简单实现困难. \(P.s\) ...
- [NOI2007]货币兑换Cash(DP+动态凸包)
第一次打动态凸包维护dp,感觉学到了超级多的东西. 首先,set是如此的好用!!!可以通过控制一个flag来实现两种查询,维护凸包和查找斜率k 不过就是重载运算符和一些细节方面有些恶心,90行解决 后 ...
- BZOJ [HAOI2011]防线修建(动态凸包)
听说有一种很高端的东西叫动态凸包维护dp就像学一下,不过介于本人还不会动态凸包就去学了下,还是挺神奇的说,维护上下凸包的写法虽然打得有点多不过也只是维护复制黏贴的事情而已罢了. 先说下动态凸包怎么写吧 ...
- 【BZOJ 2300】 2300: [HAOI2011]防线修建 (动态凸包+set)
2300: [HAOI2011]防线修建 Description 近来A国和B国的矛盾激化,为了预防不测,A国准备修建一条长长的防线,当然修建防线的话,肯定要把需要保护的城市修在防线内部了.可是A国上 ...
- BZOJ 2300: [HAOI2011]防线修建( 动态凸包 )
离线然后倒着做就变成了支持加点的动态凸包...用平衡树维护上凸壳...时间复杂度O(NlogN) --------------------------------------------------- ...
- Code Chef JUMP(递推+树状数组+李超线段树)
\(JUMP\) 很容易写出转移柿子 \[f_i=\min_{p_j<p_i}\{(h_i-h_j)^2+f_j\}+w_i\] 把\(\min\)里面的东西展开一下 \[f_j=\min_{p ...
- codeforces 70 D. Professor's task 动态凸包
地址:http://codeforces.com/problemset/problem/70/D 题目: D. Professor's task time limit per test 1 secon ...
随机推荐
- .NET中CORS跨域访问WebApi
我这里只写基本用法以作记录,具体为什么看下面的文章: http://www.cnblogs.com/landeanfen/p/5177176.html http://www.cnblogs.com/m ...
- iOS.AddFont
为iOS App 添加定制字体 http://www.developers-life.com/how-to-include-ttf-fonts-to-ios-app.html http://blog. ...
- 参看dll参数类型
http://blog.csdn.net/chinabinlang/article/details/7698459 验证
- 由已打开的文件读取数据---read
头文件:#include<unistd.h> 函数原型:ssize_t read(int fd,void *buf,size_t count); 参数说明:fd:文件描述符 buf:存放读 ...
- 系统调用方式文件编程-open
通过Linux系统调用函数编写应用程序,该应用程序实现文件的复制功能 文件描述符--在Linux系统中,所有打开的文件也对应一个数字,这个数字由系统来分配. 1.打开文件--open 头文件:#inc ...
- 2018.09.21 atcoder An Invisible Hand(贪心)
传送门 简单贪心啊. 这题显然跟t并没有关系,取差量最大的几组买入卖出就行了. 于是我们统计一下有几组差量是最大的就行了. 代码: #include<bits/stdc++.h> #def ...
- Linux服务器部署系列之二—MySQL篇
MySQL是linux环境中使用最广泛的数据库之一,著名的“LAMP黄金组合”就要用到MySQL.关于MySQL的优点及作用,我就不多讲了,网上很多这样的文章. 今天我们要谈的是MySQL服务器的部署 ...
- Asp.net mvc验证用户登录之Forms实现
这里我们采用asp.net mvc 自带的AuthorizeAttribute过滤器验证用户的身份,也可以使用自定义过滤器,步骤都是一样. 第一步:创建asp.net mvc项目, 在项目的App_S ...
- Scala包和引用
1.包 Scala包的命名方式有两种.一种和Java一样,通过把package子句放在文件顶端的方式,把整个文件的内容放进包里.如: package scala.actors.Actor 另一种方式可 ...
- SPOJ10606 BALNUM - Balanced Numbers(数位DP+状压)
Balanced numbers have been used by mathematicians for centuries. A positive integer is considered a ...