暴力写挂

题目描述

题解

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

代码

#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int N=4e5+5,N2=N<<1,N4=N<<2;
int n,m,t=1,fa[22][N2],Lg[N2],d[N],e[N],o,rt,su,hd[N2],sz[N2];
int V[N4],W[N4],nx[N4],b[N],id[N],col[N],tp,S[N],h[2][N],c;
LL dp[N],Dp[N],sm[N],f[2][N],ans=-2e18;
bool vis[N2];vector<int>X[N],Y[N];
void Add(int u,int v,int w){
    X[u].push_back(v);Y[u].push_back(w);
}
void add(int u,int v,int w){
    nx[++t]=hd[u];V[hd[u]=t]=v;W[t]=w;
}
void add(int u,int v){X[u].push_back(v);}
void rebuild(int u,int fr){
    int x=0,z=X[u].size();
    for (int v,w,i=0;i<z;i++){
        v=X[u][i];w=Y[u][i];
        if (v==fr) continue;dp[v]=dp[u]+w;
        if (!x) add(u,v,w),add(v,u,w),x=u;
        else m++,add(x,m,0),add(m,x,0),
            add(m,v,w),add(v,m,w),x=m;
        rebuild(v,u);
    }
}
void dfs(int u,int fr){
    int z=X[u].size();
    fa[0][e[u]=++c]=u;b[id[u]=++t]=u;
    for (int v,w,i=0;i<z;i++){
        v=X[u][i];w=Y[u][i];
        if (v==fr) continue;
        Dp[v]=Dp[u]+w;d[v]=d[u]+1;
        dfs(v,u);fa[0][++c]=u;
    }
}
int Min(int u,int v){return d[u]<d[v]?u:v;}
int qry(int l,int r){
    l=e[l];r=e[r];
    if (l>r) swap(l,r);int i=Lg[r-l+1];
    return Min(fa[i][l],fa[i][r-(1<<i)+1]);
}
void Sz(int u,int fr){
    sz[u]=1;
    for (int v,i=hd[u];i;i=nx[i])
        if (!vis[i>>1] && (v=V[i])!=fr)
            Sz(v,u),sz[u]+=sz[v];
}
void Rt(int u,int fr){
    for (int v,w,i=hd[u];i;i=nx[i])
        if (!vis[i>>1] && (v=V[i])!=fr){
            w=max(sz[v],o-sz[v]);
            if (w<su) rt=i,su=w;Rt(v,u);
        }
}
void find(int u,int fr,LL w,int cl){
    if (u<=n) col[u]=cl,sm[u]=w;
    for (int v,i=hd[u];i;i=nx[i])
        if (!vis[i>>1] && (v=V[i])!=fr)
            find(V[i],u,w+W[i],cl);
}
void ins(int u){
    if (tp<1){S[++tp]=u;return;}
    int x=qry(S[tp],u);
    if (x==S[tp]){S[++tp]=u;return;}
    while(tp>1 && id[S[tp-1]]>=id[x])
        add(S[tp-1],S[tp]),tp--;
    if (x!=S[tp]) add(x,S[tp]),S[tp]=x;
    S[++tp]=u;
}
void get(int u){
    int z=X[u].size();
    f[0][u]=f[1][u]=-2e18;
    if (~col[u]) f[col[u]][u]=dp[u]+sm[u];
    for (int v,i=0;i<z;i++){
        v=X[u][i];get(v);
        for (int j=0;j<2;j++)
            ans=max(ans,f[j][u]+f[!j][v]-2ll*Dp[u]);
        for (int j=0;j<2;j++)
            f[j][u]=max(f[j][u],f[j][v]);
    }
    X[u].clear();
}
void solve(int u,int l,int r){
    Sz(u,0);o=sz[u];rt=0;su=1e9;
    Rt(u,0);if (!rt) return;
    int x=V[rt],y=V[rt^1];vis[rt>>1]=1;
    find(x,y,0,0);find(y,x,W[rt],1);
    if (b[l]!=1) ins(1);
    for (int i=l;i<=r;i++) ins(b[i]);
    while(tp>1) add(S[tp-1],S[tp]),tp--;
    tp=0;get(1);int v[2]={0};
    for (int w,i=l;i<=r;i++)
        w=col[b[i]],h[w][++v[w]]=b[i],col[b[i]]=-1;
    for (int i=0;i<v[0];i++) b[i+l]=h[0][i+1];
    for (int i=0;i<v[1];i++) b[r-i]=h[1][v[1]-i];
    solve(x,l,l+v[0]-1);solve(y,r-v[1]+1,r);
}
int main(){
    cin>>n;m=n;
    for (int i=1,x,y,z;i<n;i++)
        scanf("%d%d%d",&x,&y,&z),
        Add(x,y,z),Add(y,x,z);rebuild(1,0);
    for (int i=1;i<=n;i++)
        X[i].clear(),Y[i].clear(),col[i]=-1;t=0;
    for (int i=1,x,y,z;i<n;i++)
        scanf("%d%d%d",&x,&y,&z),
        Add(x,y,z),Add(y,x,z);dfs(1,0);
    for (int i=2;i<=c;i++) Lg[i]=Lg[i>>1]+1;
    for (int i=c;i;i--)
        for (int j=1;i+(1<<j)<=c+1;j++)
            fa[j][i]=Min(fa[j-1][i],fa[j-1][i+(1<<(j-1))]);
    for (int i=1;i<=n;i++) X[i].clear();
    solve(1,1,n);ans>>=1;
    for (int i=1;i<=n;i++)
        ans=max(ans,dp[i]-Dp[i]);
    cout<<ans<<endl;return 0;
}

原文地址:https://www.cnblogs.com/xjqxjq/p/12368634.html

时间: 2024-08-30 17:55:22

暴力写挂的相关文章

CTSC2018 暴力写挂

CTSC2018 暴力写挂 题意: 题目传送门 题解: emm--第一次写边分治-- 考虑到第二棵树上的\(Lca\)我们难以处理,于是我们可以考虑枚举第二棵树上的\(Lca\),然后在第一棵树上最大化\(dep_u + dep_v - dep_{lca}\).但是在这个式子中,又受到了第一棵树上\(Lca\)的限制,于是我们考虑化简式子.稍微化简一下会发现式子变成了\(\frac{1}{2} * (dep_u + dep_v + dis_{u, v})\),然后我们就可以将其转化成无根树来做了

[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)]$$ 于是我们考虑将分治区域内的节点在第二棵

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),全称信息学奥林匹克竞赛,在这短暂的五年里,给我留下了许多难忘的回忆,就如同在夜空中一闪而过的流星,短暂却绽放出了耀眼的光芒. 记忆回到刚进入初中的时候,校内竞赛课的时间冲突使我必须在数学和信息学之间作出选择,“信息学,没听说过,好像很玩的样子”,抱