[SimpleOJ238]宝藏探寻
题目大意:
给你一棵带点权的n个结点的树,有m次询问,每次从树上删掉一条路径(u,v),问删掉每条路径后各个连通块权值和的平方之和。
每次询问是独立的。
思路:
首先对树遍历一遍求出每棵子树的权值和。
然后倍增记录下每个结点往上跳2^k层,深度范围内与这条路径无关的每个连通块的权值和的平方之和。
然后询问的时候直接倍增往上跳即可,注意跳最后一层的时候要特判一下。
#include<cstdio>
#include<cctype>
#include<vector>
typedef long long int64;
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'';
while(isdigit(ch=getchar())) x=(((x<<)+x)<<)+(ch^'');
return x;
}
const int N=;
int w[N],sum[N],par[N],dep[N];
std::vector<int> e[N];
inline void add_edge(const int &u,const int &v) {
e[u].push_back(v);
e[v].push_back(u);
}
void dfs(const int &x,const int &p) {
par[x]=p;
dep[x]=dep[p]+;
sum[x]=w[x];
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==p) continue;
dfs(y,x);
sum[x]+=sum[y];
}
}
inline int64 sqr(const int64 &x) {
return x*x;
}
inline int lca(int x,int y) {
while(x!=y) {
if(dep[x]<dep[y]) std::swap(x,y);
x=par[x];
}
return x;
}
inline int64 solve(int x,int y) {
int64 ans=;
if(x==y) {
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par[x]) continue;
ans+=sqr(sum[y]);
}
ans+=sqr(sum[]-sum[x]);
return ans;
}
if(x!=lca(x,y)) {
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par[x]) continue;
ans+=sqr(sum[y]);
}
}
std::swap(x,y);
if(x!=lca(x,y)) {
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par[x]) continue;
ans+=sqr(sum[y]);
}
}
while(par[x]!=par[y]&&x!=y) {
if(dep[x]<dep[y]) std::swap(x,y);
for(register unsigned i=;i<e[par[x]].size();i++) {
const int &y=e[par[x]][i];
if(y==par[par[x]]||y==x) continue;
ans+=sqr(sum[y]);
}
x=par[x];
}
if(x!=y) {
for(register unsigned i=;i<e[par[x]].size();i++) {
const int &to=e[par[x]][i];
if(to==par[par[x]]||to==x||to==y) continue;
ans+=sqr(sum[to]);
}
x=par[x];
}
ans+=sqr(sum[]-sum[x]);
return ans;
}
int top;
void dfs1(const int &x,const int &par) {
top=x;
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs1(y,x);
}
}
int sum2[N];
void dfs2(const int &x,const int &par) {
sum2[x]=sum[par]+w[par];
dep[x]=dep[par]+;
for(register unsigned i=;i<e[x].size();i++) {
const int &y=e[x][i];
if(y==par) continue;
dfs2(y,x);
sum[x]=sum[y]+w[y];
}
}
int main() {
int n=getint(),m=getint();
for(register int i=;i<=n;i++) {
w[i]=getint();
}
for(register int i=;i<n;i++) {
add_edge(getint(),getint());
}
if(n%==) {
dfs1(,);
dfs2(top,);
while(m--) {
int x=getint(),y=getint();
if(dep[x]<dep[y]) std::swap(x,y);
printf("%lld\n",sqr(sum[x])+sqr(sum2[y]));
}
return ;
}
dfs(,);
while(m--) {
printf("%lld\n",solve(getint(),getint()));
}
return ;
}
[SimpleOJ238]宝藏探寻的更多相关文章
- nyoj 探寻宝藏
探 寻 宝 藏 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处 ...
- 探寻宝藏(双向DP)
题目描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处处有宝物,最珍贵的宝物就藏在右下角,迷宫的进出口在左上角.当然,迷宫中的通路不是平坦 ...
- NYOJ-712 探寻宝藏(第六届河南省程序设计大赛)
探 寻 宝 藏 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫 ...
- ny712 探寻宝藏 ny61 传纸条(1)
探 寻 宝 藏 时间限制:1000 ms | 内存限制:65535 KB 难度:5 描述 传说HMH大沙漠中有一个M*N迷宫,里面藏有许多宝物.某天,Dr.Kong找到了迷宫的地图,他发现迷宫内处 ...
- 探寻宝藏 --- 双线DP
双线DP , 在郑轻的时候 做过 这种双线DP , 这是多维DP 应该是比较简单的 但是那个 时间复杂度的优化 始终看不懂 . 先附上代码吧 , 等看懂了再来 , 补充一下 解释 . #in ...
- 探寻 JavaScript 逻辑运算符(与、或)的真谛
十二月已经过半,冬季是一个美妙的季节,寒冷的空气逼得人们不得不躲在安逸舒适的环境里生活.冬季会给人一种安静祥和的氛围,让人沉浸在其中,仿佛是一个旧的阶段的结束,同时也是一个新的阶段的开始.这么说来,西 ...
- 算法:poj1066 宝藏猎人问题。
package practice; import java.util.Scanner; public class TreasureHunt { public static void main(Stri ...
- 【BZOJ-1924】所驼门王的宝藏 Tarjan缩点(+拓扑排序) + 拓扑图DP
1924: [Sdoi2010]所驼门王的宝藏 Time Limit: 5 Sec Memory Limit: 128 MBSubmit: 787 Solved: 318[Submit][Stat ...
- zzulioj 1907小火山的宝藏交易(dfs记忆化搜索)
#include <stdio.h> #include <algorithm> #include <string.h> #include <vector> ...
随机推荐
- Node.js的开源博客系统Ghost搭建教程
准备工作 Node.js版本:0.10.x.0.12.x.4.2.x.安装步骤可参考:Node.js环境搭建 Ghost版本:0.7.4:中文集成版(33.6M),中文标准版(3.39M),英文原版( ...
- C++ Boost库 uBLAS 笔记
构造 Vector #include <boost/numeric/ublas/vector.hpp> #include <boost/numeric/ublas/io.hpp> ...
- $.when()方法翻译2
mac不知道为何,文章字数一多,浏览器就重启.只好分开写了. In the event a Deferred was resolved with no value, the corresponding ...
- php中的转义函数
<?php parse_url 解析URL, 返回各组成部分 urlencode/urldecode url编码/解码 htmlentities 将字符串转化为html实体 htmlentiti ...
- Linux下多路径multipath配置【转】
一.multipath在redhat 6.2中的基本配置: 1. 通过命令:lsmod |grep dm_multipath 检查是否正常安装成功.如果没有输出说明没有安装那么通过yum功能安装一下 ...
- HDU 6195 2017沈阳网络赛 公式
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6195 题意:有M个格子,有K个物品.我们希望在格子与物品之间连数量尽可能少的边,使得——不论是选出M个 ...
- Xcode及模拟器SDK下载
http://blog.csdn.net/zhangao0086/article/details/38491271 吐槽下,百度打着无限分享的旗号,却又让分享资源过期,让分享者持续维护 如果你嫌在Ap ...
- 理解一条语句:SELECT difference(sum("value")) FROM "mq_enqueue" WHERE "channel" =~ /ActiveMQ_TEST/ AND $timeFilter GROUP BY time($interval)
最近使用grafana在查询InfluxDB中,用到了这一条语句 SELECT difference(sum("value")) FROM "mq_enqueue&quo ...
- Python静态代码检查工具Flake8
简介 Flake8 是由Python官方发布的一款辅助检测Python代码是否规范的工具,相对于目前热度比较高的Pylint来说,Flake8检查规则灵活,支持集成额外插件,扩展性强.Flake8是对 ...
- Python中的json操作
Python中的json操作 标签(空格分隔): python 编码 json 字符串前缀问题 字符串前缀可以有r,u r:表示原始(raw)字符串,比如'\n'不会被转义.常用于正则. u:表示un ...