[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> ...
随机推荐
- scrapy爬虫框架介绍
一 介绍 Scrapy一个开源和协作的框架,其最初是为了页面抓取 (更确切来说, 网络抓取 )所设计的,使用它可以以快速.简单.可扩展的方式从网站中提取所需的数据.但目前Scrapy的用途十分广泛,可 ...
- mybatis笔记之使用Mapper接口注解
1. mybatis支持的映射方式 mybatis支持的映射方式有基于xml的mapper.xml文件.基于java的使用Mapper接口class,简单学习一下mybatis使用接口来配置映射的方法 ...
- 伪ajax操作
什么是伪Ajax操作? 说白了就是假的ajax操作,但是它和正常的ajax操作的目的是一样的,把前端的信息发送到后台 先看一下代码吧! ajax.html <form action=" ...
- 去除\ufeff的解决方法,python语言
语言:python 编程工具:pycharm 硬件环境:win10 64位 读取文件过程中发现一个问题:已有记事本文件(非空),转码 UTF-8,复制到pycharm中,在开始位置打印结果会出现 \ ...
- 【UOJ#38】【清华集训2014】奇数国
考虑欧拉函数的性质,60很小,压位存下线段树每个节点出现质数. #include<bits/stdc++.h> ; ; typedef long long ll; using namesp ...
- 匿名函数、lambda表达式
匿名函数 func = lambda x: y #x是形参,y是返回值 键字lambda表示匿名函数,冒号前面的x表示函数参数,冒号后面的y表示匿名函数的返回值. 例1:返回列表中长度大于等于3的元素 ...
- scikit-learn模块学习笔记(数据预处理模块preprocessing)
本篇文章主要简单介绍sklearn中的数据预处理preprocessing模块,它可以对数据进行标准化.preprocessing 模块提供了数据预处理函数和预处理类,预处理类主要是为了方便添加到pi ...
- C++随笔(2)
在牛客网上刷题,遇到的一些需要注意的题 1.这题需要注意的是strcpy复制的时候什么时候停止 2.这题是关于strlen的,它不统计‘\0',但复制的时候仍会复制. 3.这题是写strcpy函数的, ...
- python_xlsxwriter模块
1.workbook类 add_worksheet 用于添加一个新的工作表,sheetname为工作表名称,默认是sheet1,例如: worksheet = workbook.add_workshe ...
- Codeforces 918C The Monster(括号匹配+思维)
题目链接:http://codeforces.com/contest/918/problem/C 题目大意:给你一串字符串,其中有'('.')'.'?'三种字符'?'可以当成'('或者')'来用,问该 ...