题意:给你一颗树,然后这颗树有n*n条路径,a->b和b->a算是一条,然后路径的权值是 vi*(-1)^(i+1)  注意是点有权值。

从上头往下考虑是点分治,从下向上考虑就是树形DP,分成三类路径:1.指定点单点 2.跨过指定点3.没跨过指定点但不是单点

细节要好好打磨一下,然后还是用long long比较稳 ,1LL*还是有点危险.

点分治:

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+;
const int P=1e9+;
vector<int>G[N];
bool vis[N];
int SQ,SO,Q,O,q[N],o[N],rt,m,nq[N],no[N],sz[N],v[N],mx[N],ans;
void dfs(int u,int fa,int S){
sz[u]=mx[u]=;
q[u]=o[u]=no[u]=nq[u]=;
for(int i=;i<(int)G[u].size();++i) {
int v=G[u][i];
if(vis[v]||v==fa) continue;
dfs(v,u,S);
sz[u]+=sz[v];
mx[u]=max(mx[u],sz[v]);
}
mx[u]=max(mx[u],S-sz[u]);
if(m>mx[u]) rt=u,m=mx[u];
}
void solve(int u,int nv,int f,int fa,int last){
int t=(nv+f*v[u])%P;
if(f==-) o[fa]=(o[fa]+t)%P,O=(O+t)%P,++no[fa],++SO;
else q[fa]=(q[fa]+t)%P,Q=(Q+t)%P,++nq[fa],++SQ;
for(int i=;i<(int)G[u].size();++i) {
int v=G[u][i];
if(v==last||vis[v]) continue;
solve(v,t,-f,fa,u);
}
}
int work(int u,int S){
m=1e9+;
dfs(u,,S);
vis[rt]=;
Q=O=SQ=SO=;
for(int i=;i<(int)G[rt].size();++i) if(!vis[G[rt][i]]) solve(G[rt][i],v[rt],-,G[rt][i],rt);
for(int i=;i<(int)G[rt].size();++i) if(!vis[G[rt][i]]){
int t=G[rt][i];
ans=((ans-1LL*no[t]*(O-o[t])%P)%P-1LL*o[t]*(SO-no[t])%P)%P;
ans=(ans+1LL*no[t]*(SO-no[t])%P*v[rt]%P)%P;
ans=((ans+1LL*nq[t]*(Q-q[t])%P)%P+1LL*q[t]*(SQ-nq[t])%P)%P;
ans=(ans-1LL*nq[t]*(SQ-nq[t])%P*v[rt]%P)%P;
ans=(ans+(q[t]<<)%P)%P;
}
ans=((ans+v[rt])%P+P)%P;
int nt=rt;
for(int i=;i<(int)G[nt].size();++i) if(!vis[G[nt][i]])
work(G[nt][i],sz[G[nt][i]]>sz[nt]?S-sz[nt]:sz[G[nt][i]]);
}
int main(){
int n,x,y;
scanf("%d",&n);
for(int i=;i<=n;++i) scanf("%d",v+i);
for(int i=;i<n;++i) {
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
work(,n);
printf("%d\n",(ans+P)%P);
}

树形DP的思路是参考的这里

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=2e5+;
const int P=1e9+;
vector<int>G[N];
long long dp[N][],num[N][],ans,v[N];
void dfs(int u,int fa){
for(int i=;i<(int)G[u].size();++i) {
int vt=G[u][i];
if(vt==fa) continue;
dfs(vt,u);
dp[u][]=(((dp[u][]+dp[vt][])%P-1LL*v[u]*num[vt][]%P)%P+P)%P;
dp[u][]=(((dp[u][]+dp[vt][])%P+1LL*v[u]*num[vt][]%P)%P+P)%P;
num[u][]=(num[u][]+num[vt][])%P;
num[u][]=(num[u][]+num[vt][])%P;
}
for(int i=;i<(int)G[u].size();++i) {
int vt=G[u][i];
if(vt==fa) continue;
ans=(ans+2LL*(num[u][]-num[vt][])%P*dp[vt][]%P+1LL*(num[u][]-num[vt][])*v[u]%P*num[vt][]%P)%P;
ans=(ans+2LL*(num[u][]-num[vt][])%P*dp[vt][]%P-1LL*(num[u][]-num[vt][])*v[u]%P*num[vt][]%P)%P;
}
ans=(ans+(dp[u][]<<)%P+v[u])%P;
++num[u][];
num[u][]%=P;
dp[u][]=(dp[u][]+v[u])%P;
}
int main(){
int n,x,y;
scanf("%d",&n);
for(int i=;i<=n;++i) scanf("%lld",v+i);
for(int i=;i<n;++i) {
scanf("%d%d",&x,&y);
G[x].push_back(y);
G[y].push_back(x);
}
dfs(,);
printf("%lld\n",(ans+P)%P);
}

E. Alternating Tree 树点分治|树形DP的更多相关文章

  1. 算法笔记--树的直径 && 树形dp && 虚树 && 树分治 && 树上差分 && 树链剖分

    树的直径: 利用了树的直径的一个性质:距某个点最远的叶子节点一定是树的某一条直径的端点. 先从任意一顶点a出发,bfs找到离它最远的一个叶子顶点b,然后再从b出发bfs找到离b最远的顶点c,那么b和c ...

  2. (中等) HDU 5293 Tree chain problem,树链剖分+树形DP。

    Problem Description   Coco has a tree, whose vertices are conveniently labeled by 1,2,…,n.There are ...

  3. [集训队作业2018]蜀道难——TopTree+贪心+树链剖分+链分治+树形DP

    题目链接: [集训队作业2018]蜀道难 题目大意:给出一棵$n$个节点的树,要求给每个点赋一个$1\sim n$之内的权值使所有点的权值是$1\sim n$的一个排列,定义一条边的权值为两端点权值差 ...

  4. CF F - Tree with Maximum Cost (树形DP)给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大。输出最大的值。

    题目意思: 给出你一颗带点权的树,dist(i, j)的值为节点i到j的距离乘上节点j的权值,让你任意找一个节点v,使得dist(v, i) (1 < i < n)的和最大.输出最大的值. ...

  5. [codeforces161D]Distance in Tree(点分治/树形dp)

    题意:求树上距离为k的点对个数: 解题关键:练习一下点分治不用容斥 而直接做的做法.注意先查询,后更新. 不过这个方法有个缺陷,每次以一个新节点为根,必须memset mp数组,或许使用map会好些, ...

  6. 『You Are Given a Tree 整体分治 树形dp』

    You Are Given a Tree Description A tree is an undirected graph with exactly one simple path between ...

  7. [BZOJ2152]聪聪可可 点分治/树形dp

    2152: 聪聪可可 Time Limit: 3 Sec  Memory Limit: 259 MB Submit: 3602  Solved: 1858 [Submit][Status][Discu ...

  8. BZOJ 2152 / Luogu P2634 [国家集训队]聪聪可可 (点分治/树形DP)

    题意 一棵树,给定边权,求满足两点之间的路径上权值和为3的倍数的点对数量. 分析 点分治板题,对每个重心求子树下面的到根的距离模3分别为0,1,2的点的个数就行了. O(3nlogn)O(3nlogn ...

  9. 2014 Super Training #9 E Destroy --树的直径+树形DP

    原题: ZOJ 3684 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3684 题意: 给你一棵树,树的根是树的中心(到其 ...

随机推荐

  1. Spring Boot中使用Swagger CodeGen生成REST client

    文章目录 什么是Open API规范定义文件呢? 生成Rest Client 在Spring Boot中使用 API Client 配置 使用Maven plugin 在线生成API Spring B ...

  2. SQL计算算数表达式的函数自定义(加减乘除)

    一.整体思路:循环遍历表达式字符串,设置一个index从第一个字符开始检测当前数字是否可以和后面的数字进行运算,如果可以运算,将两个数挑出来运算,然后用运算的结果替换原来表达式中的这两个数和符号,计算 ...

  3. 【JAVA基础】07 面向对象2

    1. 代码块的概述和分类 面试的时候会问,开发不用或者很少用 代码块概述 在Java中,使用 {} 括起来的代码被称为代码块. 代码块分类 根据其位置和声明的不同,可以分为局部代码块,构造代码块,静态 ...

  4. if __name=='__main__"的作用

    1.__main__的作用 我们可以经常在不同的程序和脚本中看到有这样的代码: if __name__=='__main__':#如果在windows上启动线程池,必须要使用. func() 很多情况 ...

  5. 网速慢?NO可能是路由器的原因?

    先排除DNS的问题:看这个! 为什么我家300M的网,而且wifi信号满格,还是网速很慢? 这时候不排除是路由器的原因! 第一步首先我们要知道自己家的网关IP: 什么是网关? 网关(Gateway)又 ...

  6. Codeforces Round #561 (Div. 2) A. Silent Classroom(贪心)

    A. Silent Classroom time limit per test1 second memory limit per test256 megabytes inputstandard inp ...

  7. Linux 上搭建 Snort+BASE 入侵检测系统

    配置实验环境 由于本人电脑的存储空间不足,无法再承担安装一个虚拟机的开销,因此在阿里云上申请了一个云服务器进行本次实验.服务器配置如下: 1 核 - 2GB 内存 - 40GB 系统盘 操作系统:Ub ...

  8. Java:手写幼儿园级线程安全LRU缓存X探究影响命中率的因素

    最近遇到一个需求,需要频繁访问数据库,但是访问的内容只是 id + 名称 这样的简单键值对. 频繁的访问数据库,网络上和内存上都会给数据库服务器带来不小负担. 于是打算写一个简单的LRU缓存来缓存这样 ...

  9. 区间dp E - Multiplication Puzzle POJ - 1651

    E - Multiplication Puzzle  POJ - 1651 这个题目没有特别简单,但是也没有我想象之中的那么难,这个题目时区间dp,因为我们是要对区间进行考虑的. 但是呢,这个也和动态 ...

  10. CSS中的间距设置与盒子模型

    CSS间距 内补白 外补白 盒子模型 CSS间距 很多时候我们为了美观,需要对内容进行留白设置,这时候就需要设置间距了. 内补白 设置元素的内间距 padding: 检索或设置对象四边的内部边距 pa ...