CTSC2018 暴力写挂

CTSC2018 暴力写挂

题意:

题目传送门

题解:

emm……第一次写边分治……
考虑到第二棵树上的\(Lca\)我们难以处理,于是我们可以考虑枚举第二棵树上的\(Lca\),然后在第一棵树上最大化\(dep_u + dep_v - dep_{lca}\)。但是在这个式子中,又受到了第一棵树上\(Lca\)的限制,于是我们考虑化简式子。稍微化简一下会发现式子变成了\(\frac{1}{2} * (dep_u + dep_v + dis_{u, v})\),然后我们就可以将其转化成无根树来做了。
考虑边分的时候我们应该维护什么东西,我们将\(dis_{u, v}\)拆成\(dis_{u, rt} + dis_{rt, v}\),其中\(rt\)为当前边分中心的两个点其中的一个点。那么我们就只需要维护\(dis_{x, rt} + dep_x\)的最大值即可。然后我们在第二棵树上枚举\(Lca\),然后计算贡献即可。最后就是如何合并两个点的贡献,发现我们重建之后的边分树是一棵二叉树,它有着线段树的形态,所以我们直接像线段树合并一样将贡献合并起来即可,复杂度是正确的。

Code

#pragma GCC optimize (2,"inline","Ofast")
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 4e5 + 500;
typedef pair<int, int> P;
const ll INF = 1e15;
#define fi first
#define se second
#define mk make_pair

struct Graph {
    struct edge {
        int to, nxt, w;
    }E[N << 3];
    int head[N << 2];
    int tot;
    Graph() { tot = 1; memset(head, -1, sizeof head);}
    void Addedge(int u, int v, int w) {
        E[++tot].to = v; E[tot].nxt = head[u]; head[u] = tot; E[tot].w = w;
        E[++tot].to = u; E[tot].nxt = head[v]; head[v] = tot; E[tot].w = w;
    }
    void Print() {
        for(int i = 2; i <= tot; i += 2) {
            cerr << E[i].to << " " << E[i ^ 1].to << endl;
        }
    }
}T1, T2, DvT;

int n, ndcnt, Mn, id, cnt;
int sz[N << 2], vis[N << 3], ch[N << 6][2], rt[N << 2];
P PA[N << 2];
ll val[N << 6][2], dep[N];
ll ans = -INF;

void read(int &x) {
    x = 0; int f = 1; char ch = getchar();
    while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
    while(ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    x *= f;
}

void Rebuild(int o, int fa) {
    int las = o;
    for(int i = T1.head[o]; ~i; i = T1.E[i].nxt) {
        int to = T1.E[i].to;
        if(to == fa) continue;
        dep[to] = dep[o] + T1.E[i].w;
        Rebuild(to, o);
        DvT.Addedge(las, ++ndcnt, 0); DvT.Addedge(ndcnt, to, T1.E[i].w);
        las = ndcnt;
    }
}

void GetEg(int o, int fa, int SZ) {
    sz[o] = 1;
    for(int i = DvT.head[o]; ~i; i = DvT.E[i].nxt) {
        int to = DvT.E[i].to;
        if(to == fa || vis[i]) continue ;
        GetEg(to, o, SZ);
        sz[o] += sz[to];
        if(Mn > max(sz[to], SZ - sz[to])) Mn = max(sz[to], SZ - sz[to]), id = i;
    }
}

void Getdep(int o, int fa, ll d, int c) {
    if(o <= n) {
        ++cnt;
        if(!PA[o].fi) rt[o] = cnt;
        else ch[PA[o].fi][PA[o].se] = cnt;
        PA[o] = mk(cnt, c);
        val[cnt][c] = dep[o] + d;
        val[cnt][c ^ 1] = -INF;
    }
    sz[o] = 1;
    for(int i = DvT.head[o]; ~i; i = DvT.E[i].nxt) {
        int to = DvT.E[i].to;
        if(to == fa || vis[i]) continue ;
        Getdep(to, o, d + DvT.E[i].w, c);
        sz[o] += sz[to];
    }
}

void Solve(int o, int SZ) {
    if(SZ == 1) return ;
    Mn = 1e9;  GetEg(o, 0, SZ);
    int x = DvT.E[id].to, y = DvT.E[id ^ 1].to;
    vis[id] = vis[id ^ 1] = 1;
    Getdep(x, 0, 0, 0); Getdep(y, 0, DvT.E[id].w, 1);
    Solve(x, sz[x]); Solve(y, sz[y]);
}

int Merge(int x, int y, ll Dp) {
    if(!x || !y) return x | y;
    ans = max(ans, max(val[x][0] + val[y][1], val[x][1] + val[y][0]) - Dp);
    val[x][0] = max(val[x][0], val[y][0]); ch[x][0] = Merge(ch[x][0], ch[y][0], Dp);
    val[x][1] = max(val[x][1], val[y][1]); ch[x][1] = Merge(ch[x][1], ch[y][1], Dp);
    return x;
}

void Dfs(int o, int fa, ll d) {
    ans = max(ans, 2ll * (dep[o] - d));
    for(int i = T2.head[o]; ~i; i = T2.E[i].nxt) {
        int to = T2.E[i].to;
        if(to == fa) continue;
        Dfs(to, o, d + T2.E[i].w);
        rt[o] = Merge(rt[o], rt[to], d * 2);
    }
}

int main() {
    read(n); ndcnt = n;
    for(int i = 1, u, v, w; i < n; i++) {
        read(u); read(v); read(w);
        T1.Addedge(u, v, w);
    }
    for(int i = 1, u, v, w; i < n; i++) {
        read(u); read(v); read(w);
        T2.Addedge(u, v, w);
    }
    Rebuild(1, 1);
    Solve(1, ndcnt);
    Dfs(1, 0, 0);
    printf("%lld\n", ans / 2);
    return 0;
}

原文地址:https://www.cnblogs.com/Apocrypha/p/10569832.html

时间: 2024-10-03 23:11:01

CTSC2018 暴力写挂的相关文章

[CTSC2018]暴力写挂——边分树合并

[CTSC2018]暴力写挂 题面不错 给定两棵树,两点“距离”定义为:二者深度相加,减去两棵树上的LCA的深度(深度指到根节点的距离) 求最大的距离. 解决多棵树的问题就是降维了. 经典的做法是边分树合并. 边分树结构类似0/1 trie 就是把边分树对于每个点拆开路径 合并两棵边分树同时可以得到两个边分树之间点对的路径的信息 感觉有点类似线段树合并. 根据“猫树”思想,两点间的路径一定经过边分树上LCA的那条边.(u,v不相等) 我们考虑在这个LCA处统计贡献 具体地,先对1树进行边分治 每

Loj #2553. 「CTSC2018」暴力写挂

Loj #2553. 「CTSC2018」暴力写挂 题目描述 temporaryDO 是一个很菜的 OIer .在 4 月,他在省队选拔赛的考场上见到了<林克卡特树>一题,其中 \(k = 0\) 的部分分是求树 \(T\) 上的最长链.可怜的 temporaryDO 并不会做这道题,他在考场上抓猫耳挠猫腮都想不出一点思路. 这时,善良的板板出现在了空中,他的身上发出璀璨却柔和的光芒,荡漾在考场上.''题目并不难.'' 板板说.那充满磁性的声音,让 temporaryDO 全身充满了力量. 他

uoj#400. 【CTSC2018】暴力写挂(边分治)

传送门 做一道题学一堆东西.jpg 猫老师的题--暴力拿的分好像比打挂的正解多很多啊--我纯暴力+部分分已经能有80了--正解没调对之前一直只有10分→_→ 先说一下什么是边分治.这个其实类似于点分治,不过分治对象从点换成边了,就是每次找到一条边,使其断开之后的两个连通块中最大的最小 于是我们就可以--等会儿如果在菊花图上怎么办?不是得卡到\(O(n^2)\)了? 不难发现这个东西的复杂度和节点的度数有关,于是为了假装这个东西能用避免这些情况,我们要把图给重构喽 简单来说就是通过加入虚点,把图给

UOJ#400. 【CTSC2018】暴力写挂 边分治 线段树合并

原文链接 www.cnblogs.com/zhouzhendong/p/UOJ400.html 前言 老年选手没有码力. 题解 先对第一棵树进行边分治,然后,设点 x 到分治中心的距离为 $D[x]$,点 x 在原树上的深度为 $d[x]$,那么 $$d[x]+d[y] - d[LCA(x,y)] - d'[LCA(x,y)] = \frac 12(D[x] + d[x]) + \frac 12 (D[y] + d[y]) - d'[LCA(x,y)]$$ 于是我们考虑将分治区域内的节点在第二棵

暴力写挂

题目描述 题解 考虑把式子化一下,因为只有一个式子跟第二棵树有关,所以我们可以考虑把前面的式子化成跟 $\text{lca}$ 没有关系,即 $\frac{1}{2}(dp_u+dp_v+dis(u,v))$ .因此我们可以利用边分治,每次把两边的点黑白染色,构成虚树,然后做 $\text{dp}$ 即可.这里要注意 $\text{lca}$ 要 $O(1)$ 求,虚树构成过程中不能排序,故我们可以一开始就按照第二棵树的dfs排序好,之后分治下去即可.效率: $O(nlogn)$ . 代码 #i

1134 最长递增子序列(暴力写的)

可以用二分写... 基准时间限制:1 秒 空间限制:131072 KB 分值: 0 难度:基础题  收藏  关注 给出长度为N的数组,找出这个数组的最长递增子序列.(递增子序列是指,子序列的元素是递增的) 例如:5 1 6 8 2 4 5 10,最长递增子序列是1 2 4 5 10. Input 第1行:1个数N,N为序列的长度(2 <= N <= 50000) 第2 - N + 1行:每行1个数,对应序列的元素(-10^9 <= S[i] <= 10^9) Output 输出最长

AHOI2017游记

话说省选也过去好几天了--按照oi届传统补个游记吧--这可能是我第一次写游记-- DAY -n 省选之前超级心慌--于是出去培训--首先到长沙并且成功抱到了几个大佬的大腿,在那里的模拟赛非常不稳每次写题都有暴力写挂,接着马不停蹄去了杭州二中然后体会到了被碾压的酸爽--场场垫底--情绪一度非常不稳觉得自己应该是要退役了.回来天天颓颓颓,补完了男子高中生的日常,听了很多刘宝瑞的相声. DAY 0     内心毫无波动地到了合肥一中,发现自己和稳爷爷还有安师大附中的几个dalao一个考场--感觉比较妙

NOIp2016 Day1&amp;Day2 解题报告

Day1 T1 toy 本题考查你会不会编程. //toy //by Cydiater //2016.11.19 #include <iostream> #include <cstdlib> #include <cstdio> #include <cstring> #include <string> #include <algorithm> #include <queue> #include <map> #in

再见,OI

2015年7月19日,杭州正赤日炎炎,知了喧嚣着,学军中学的大体育馆内却鸦雀无声.“NOI2015Day2比赛结束!”,伴随着王宏主席一声令下,我5年的OI生涯也正式宣告结束,是时候说声再见了. OI(Olympiad in Informatics),全称信息学奥林匹克竞赛,在这短暂的五年里,给我留下了许多难忘的回忆,就如同在夜空中一闪而过的流星,短暂却绽放出了耀眼的光芒. 记忆回到刚进入初中的时候,校内竞赛课的时间冲突使我必须在数学和信息学之间作出选择,“信息学,没听说过,好像很玩的样子”,抱