前言

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

题解

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

倍增维护四个值:

  链上最大值/最小值

  链向上/向下最大差值

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

然后把一条链经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. python logger 日志模块

    logger 日志 """logging配置""" import osimport logging.config # 定义三种日志输出格式 ...

  2. Mysql-慢查询排查

    1.开启慢日志 2.使用show full processlist抓出慢查询语句 3.使用explain分析语句 4. set global profiling = ON

  3. c++实现直接插入排序

    基本概念 直接插入排序是一种最简单的排序方法,排序过程为:先将第一个元素看作是只有一个元素的有序子表,然后从第二个元素开始,将待排序元素依次插入到前面有序的子表中,直到全部排序完毕.在整个过程中,前面 ...

  4. Codeforces 1215D. Ticket Game

    传送门 博弈,发现情况有点多,分析一下把有用的状态提取出来 显然各个位置的数字是没用的,我们只要知道两边的数字和分别是多少 并且状态显然和左右两边的 "?" 数量有关 因为最终我们 ...

  5. css3 伪类以及伪元素的特效

    菱形          

  6. Restful 架构方式的 web service

    现在公司项目用的apache wink 搭建的web service ,感觉挺好用的.顺便学习一个这种架构方式 . 个人理解apache 实现Restful 架构方式技术有两种,如果有其他新的知识或不 ...

  7. python 解决cv2绘制中文乱码

    因为使用cv2.putText() 只能显示英文字符,中文会出现乱码问题, 因此使用PIL在图片上绘制添加中文,可以指定字体文件. 大体思路: OpenCV图片格式转换成PIL的图片格式: 使用PIL ...

  8. NSUserDefaults的用法

    NSUserDefaults适合存储轻量级的本地数据,比如要保存一个登陆界面的数据,用户名.密码之类的,个人觉得使用NSUserDefaults是首选.下次再登陆的时候就可以直接从NSUserDefa ...

  9. Linux学习--第十二天--服务、ps、top、pstree、kill、&、jobs、fg、vmstat、dmesg、free、uptime、uname、crontab、ls

    服务分类 linux服务分为rpm包默认安装的服务和源码包安装的服务. rpm包默认安装的服务分为独立的服务和基于xinetd服务. 查询已安装的服务 rpm包安装的服务 chkconfig --li ...

  10. html-DOM了解

    什么是 HTML DOM? HTML DOM 是: HTML 的标准对象模型 HTML 的标准编程接口 W3C 标准 HTML DOM 定义了所有 HTML 元素的对象和属性,以及访问它们的方法. 换 ...