前言

这道题目珂以说是很毒瘤了。

题解

首先克鲁斯卡尔求最大生成树,输出边权和。

倍增维护四个值:

  链上最大值/最小值

  链向上/向下最大差值

当然祖先是肯定要维护的。

然后把一条链经LCA分成两半。

分向上向下按照之前维护的值动态计算。

最后注意多组数据的维护(清空数组,边数之类的变量)。

代码

#include <cstdio>
#include <cstring>
#include <algorithm> using namespace std; const int LOG_N = 15;
const int INF = 1 << 28; namespace fast_IO{
const int OUT_LEN = 10000000;
char obuf[OUT_LEN], *oh = obuf, *lastout = obuf + OUT_LEN - 1;
inline void putchar_(const char x){if(oh == lastout) fwrite(obuf, 1, oh - obuf, stdout), oh = obuf; *oh ++= x;}
inline void flush(){fwrite(obuf, 1, oh - obuf, stdout);}
void write(int x){
if (x < 0) putchar_('-'), x = -x;
if (x > 9) write(x / 10);
putchar_(x % 10 + '0');
}
} using namespace fast_IO; struct Node{
int anc;
int min, max;
int udif, ddif;
} f[30005][LOG_N + 1]; struct PreEdge{
int u, v, w;
} pre_edge[50005]; bool operator < (const PreEdge &a, const PreEdge &b){
return a.w > b.w;
} struct Edge{
int to, val, next;
} edges[60005]; int head[30005], edge_num; inline void addEdge(int from, int to, int val){
edges[++edge_num] = (Edge){to, val, head[from]};
head[from] = edge_num;
} int n;
int c[30005];
int fa[30005]; int getF(int u){
if (fa[u] == u) return u;
return (fa[u] = getF(fa[u]));
} int deep[30005]; void preDFS(int u, int fat){
deep[u] = deep[fat] + 1;
f[u][0] = (Node){fat, c[fat], c[fat], -INF, -INF};
for (int i = 1; i <= LOG_N; ++i)
f[u][i] = (Node){
f[f[u][i - 1].anc][i - 1].anc,
min(f[u][i - 1].min, f[f[u][i - 1].anc][i - 1].min), max(f[u][i - 1].max, f[f[u][i - 1].anc][i - 1].max),
max(max(f[u][i - 1].udif, f[f[u][i - 1].anc][i - 1].udif), f[u][i - 1].max - f[f[u][i - 1].anc][i - 1].min),
max(max(f[u][i - 1].ddif, f[f[u][i - 1].anc][i - 1].ddif), f[f[u][i - 1].anc][i - 1].max - f[u][i - 1].min)
};
for (int c_e = head[u]; c_e; c_e = edges[c_e].next){
int v = edges[c_e].to;
if (v != fat)
preDFS(v, u);
}
} int LCA(int x, int y){
if (deep[x] < deep[y]) swap(x, y);
for (int i = LOG_N; ~i; --i)
if (deep[f[x][i].anc] >= deep[y]) x = f[x][i].anc;
if (x == y) return x;
for (int i = LOG_N; ~i; --i)
if (f[x][i].anc != f[y][i].anc) x = f[x][i].anc, y = f[y][i].anc;
return f[x][0].anc;
} int ans_min, ans_max;
int ans; void getUp(int x, int y){
ans_max = max(ans_max, c[x]);
for (int i = LOG_N; i >= 0; --i){
if (deep[f[x][i].anc] > deep[y]){
ans = max(ans, ans_max - f[x][i].min);
ans_max = max(ans_max, f[x][i].max);
ans = max(ans, f[x][i].udif);
x = f[x][i].anc;
}
}
} void getDown(int x, int y){
ans_min = min(ans_min, c[x]);
for (int i = LOG_N; i >= 0; --i){
if (deep[f[x][i].anc] >= deep[y]){
ans = max(ans, f[x][i].max - ans_min);
ans_min = min(ans_min, f[x][i].min);
ans = max(ans, f[x][i].ddif);
x = f[x][i].anc;
}
}
} inline void init(){
memset(c, 0, sizeof(c));
memset(f, 0, sizeof(f));
memset(edges, 0, sizeof(edges));
memset(pre_edge, 0, sizeof(pre_edge));
memset(deep, 0, sizeof(deep));
memset(head, 0, sizeof(head));
edge_num = 0;
} int main(){
while (scanf("%d", &n) == 1 && n){
init();
for (int i = 1; i <= n; ++i) scanf("%d", &c[i]), fa[i] = i;
int m; scanf("%d", &m);
for (int i = 0; i < m; ++i){
int u, v, w; scanf("%d %d %d", &u, &v, &w);
pre_edge[i] = (PreEdge){u, v, w};
}
sort(pre_edge, pre_edge + m); ans = 0;
for (int i = 0, j = 0; i < m; ++i){
int rtu = getF(pre_edge[i].u), rtv = getF(pre_edge[i].v);
if (rtu != rtv){
fa[rtu] = rtv; ans += pre_edge[i].w;
addEdge(pre_edge[i].u, pre_edge[i].v, pre_edge[i].w);
addEdge(pre_edge[i].v, pre_edge[i].u, pre_edge[i].w);
++j;
if (j == n - 1) break;
}
}
write(ans), putchar_('\n');
preDFS(1, 1);
int q; scanf("%d", &q);
while (q--){
int x, y; scanf("%d %d", &x, &y);
int xylca = LCA(x, y);
ans = 0, ans_min = INF, ans_max = -INF;
getUp(y, xylca), getDown(x, xylca);
ans = max(ans, ans_max - ans_min);
write(ans); putchar_('\n');
}
}
flush(); return 0;
}

[ZOJ3649]Social Net 题解的更多相关文章

  1. 【做题】zoj3649 Social Net——倍增

    这题是吴老师推荐的,于是我就去做了. 根据题意,在完成最大生成树后,对于树上从x到y的一条路径,求出最大的ck-cj(j<=k,ci为路径上第i个点的权值). 我一开始的想法是二分,记路径xy的 ...

  2. ZOJ3649 Social Net

    题目链接:http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3649 这题倍增维护信息之多,也能算是一道毒瘤题了-- 解题思路 ...

  3. PAT甲题题解-1107. Social Clusters (30)-PAT甲级真题(并查集)

    题意:有n个人,每个人有k个爱好,如果两个人有某个爱好相同,他们就处于同一个集合.问总共有多少个集合,以及每个集合有多少人,并按从大到小输出. 很明显,采用并查集.vis[k]标记爱好k第一次出现的人 ...

  4. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 D题题解

    将题意转换为一开始\(t = 0\),第\(i\)个操作是令\(t \leftarrow (a_i + 1) t + (a_i + b_i + 1)\).记\(A_i = a_i + 1, B_i = ...

  5. Social Infrastructure Information Systems Division, Hitachi Programming Contest 2020 C题题解

    首先,我们将题目理解成若\(i\)与\(j\)距离恰好为\(3\),则不可能\(p_i \equiv p_j \equiv 1 \space or \space 2 (\bmod 3)\).这就相当于 ...

  6. [题解] Atcoder ABC 225 H Social Distance 2 生成函数,分治FFT

    题目 首先还没有安排座位的\(m-k\)个人之间是有顺序的,所以先把答案乘上\((m-k)!\),就可以把这些人看作不可区分的. 已经确定的k个人把所有座位分成了k+1段.对于第i段,如果我们能求出这 ...

  7. PAT甲级题解(慢慢刷中)

    博主欢迎转载,但请给出本文链接,我尊重你,你尊重我,谢谢~http://www.cnblogs.com/chenxiwenruo/p/6102219.html特别不喜欢那些随便转载别人的原创文章又不给 ...

  8. Tarjan & LCA 套题题目题解

    刷题之前来几套LCA的末班 对于题目 HDU 2586 How far away 2份在线模板第一份倍增,倍增还是比较好理解的 #include <map> #include <se ...

  9. HDU3849-By Recognizing These Guys, We Find Social Networks Useful(无向图的桥)

    By Recognizing These Guys, We Find Social Networks Useful Time Limit: 2000/1000 MS (Java/Others)     ...

随机推荐

  1. Mysql数据库表结构设计准则

    一:动静分离 解释:最好做好静态表和动态表的分离.这里解释一下静态表和动态表的含义,静态表:存储着一些固定不变的资源,比如城市/地区名/国家(静态表一定要使用缓存).动态表:一些频繁修改的表 二:关于 ...

  2. 声明一个LIst类型的数组

    ArrayList[] graphArrayList = new ArrayList[4]; for(int i=0;i<graphArrayList.length;i++){ graphArr ...

  3. python 9*9乘法口诀 猜数字游戏

  4. hashlib模块和hmac模块

    hashlib模块和hmac模块 hashlib模块 一.导入方式 import hashlib 二.作用 无论你丢什么字符串,他都会返回一串 固定长度的字符串 三.模块功能 3.1 经常使用 imp ...

  5. day 17 模块

    模块是什么? 抖音: 20万行代码全部放在一个py文件中? 为什么不行? 1. 代码太多,读取代码耗时太长. 代码不容易维护. 所以我们怎么样? 一个py文件拆分100文件,100个py文件又有相似相 ...

  6. 带EFI支持的GRUB2安装全记录

    版权归作者所有,任何形式转载请联系作者. 作者:keenshoes(来自豆瓣) 来源:https://www.douban.com/note/210077866/  关键词:EFIGRUB2efibo ...

  7. JavaEE--JSP指令

    JSP指令用于提供整个JSP页面的相关信息以及用于JSP页面与容器之间的通信.JSP指令有三种:page指令.include指令.taglib指令 1.page指令 用于设定整个JSP页面的属性和相关 ...

  8. centos7配置fastdfs集群(5.09)

    centos7配置fastdfs集群(5.09) 2017年03月10日 23:34:26 带鱼兄 阅读数 1564    版权声明:本文为博主原创文章,转载请注明出处. https://blog.c ...

  9. 《一头扎进》系列之Python+Selenium自动化测试框架实战篇6 - 价值好几K的框架,呦!这个框架还真牛叉哦!!!

    1. 简介 本文开始介绍如何通过unittest来管理和执行测试用例,这一篇主要是介绍unittest下addTest()方法来加载测试用例到测试套件中去.用addTest()方法来加载我们测试用例到 ...

  10. c#HtmlAgilityPack解析html

    通过HtmlAgilityPack实现对html页面解析HtmlDocument doc = new HtmlDocument(); doc.Load(yourStream); var itemLis ...