牛客挑战赛45 D.坐标

题目链接

题目大意:题目说得很清楚。

题解思路:由于T2生成随机&&修改随机,所以平均每次修改都在log级别!我们考虑对于 T1上的每个点下面再挂一个点,边权为在 T2中的深度。此时两点的距离即为两个节点新挂的节点的距离。由于边权非负,所以我们等价于维护新树上的直径。那么该如何动态维护直径呢?

可以欧拉序上建线段树维护。

前置技能:1.欧拉序  2.线段树

想学如何动态维护树直径的同学我强烈推荐这三篇博客

https://www.cnblogs.com/Mrzdtz220/p/11664538.html

https://zhuanlan.zhihu.com/p/84236967

https://www.cnblogs.com/TinyWong/p/11260601.html

 


不过单这题而言我的做法并不是正解,出题人似乎是利用了树的某些性质可以省去线段树维护这一操作,不过像我这样比较笨的人就只会用数据结构暴力维护啦。

 

#include<bits/stdc++.h>
//#include<tr1/unordered_map>
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
#define ls l,mid,rt<<1
#define rs mid+1,r,rt<<1|1
#define endl '\n'
#define ps puts("###")
#define int long long
const int MAXN = 4e5+10;
const double EPS = 1e-12;
const ll mod = 1e9+7;
//tr1::unordered_map<int,int>ump;
ll Max(ll a,ll b,ll c){
    if(a>=b&&a>=c)return a;
    if(b>=a&&b>=c)return b;
    return c;
}

int n,m;
int dfn[MAXN],in[MAXN],out[MAXN];
ll dep1[MAXN],dep2[MAXN],dis[MAXN];
ll ans[MAXN<<2],maxL[MAXN<<2],maxR[MAXN<<2],val[MAXN<<2],minv[MAXN<<2];
struct node{
    int to;
    ll cost;
};
vector<node>G1[MAXN],G2[MAXN];

void dfs2(int u,int fa){
    for(auto v:G2[u]){
        if(v.to==fa)continue;
        dep2[v.to]=dep2[u]+v.cost;
        dfs2(v.to,u);
    }
}

int tot;
void dfs3(int u,int fa){
    dfn[++tot]=u; in[u]=tot;
    for(auto v:G1[u]){
        if(v.to==fa)continue;
        dep1[v.to]=dep1[u]+v.cost;
        dfs3(v.to,u);
        dfn[++tot]=u;
    }
    out[u]=tot;
}

void Pushup(int rt){
    val[rt]=max(val[rt<<1],val[rt<<1|1]);
    minv[rt]=max(minv[rt<<1],minv[rt<<1|1]);
    maxL[rt]=Max(maxL[rt<<1],maxL[rt<<1|1],val[rt<<1]+minv[rt<<1|1]);
    maxR[rt]=Max(maxR[rt<<1],maxR[rt<<1|1],val[rt<<1|1]+minv[rt<<1]);
    ans[rt]=Max(ans[rt<<1],ans[rt<<1|1],max(maxL[rt<<1]+val[rt<<1|1],maxR[rt<<1|1]+val[rt<<1]));
}

void Build(int l,int r,int rt){
    if(l==r){
        val[rt]=dep1[dfn[l]];
        minv[rt]=-2*dep1[dfn[l]];
        maxL[rt]=maxR[rt]=-dep1[dfn[l]];
        ans[rt]=0;
        return ;
    }
    int mid=(l+r)/2;
    Build(ls);
    Build(rs);
    Pushup(rt);
}

void Update(int l,int r,int rt,int pos,ll c){
    if(l==r&&l==pos){
        val[rt]+=c;
        maxL[rt]-=c;
        maxR[rt]-=c;
        minv[rt]-=2*c;
        return ;
    }
    int mid=(l+r)/2;
    if(pos<=mid)Update(ls,pos,c);
    else Update(rs,pos,c);
    Pushup(rt);
}

void dfs4(int u,ll k){
    Update(1,tot,1,in[u+200000],k);
    //Update(1,tot,1,out[u+100000],-k);
    for(auto v:G2[u]){
        if(dep2[v.to]<=dep2[u])continue;
        dfs4(v.to,k);
    }
}

void solve(){
    cin>>n>>m;
    for(int i=1,u,v,w;i<n;i++){
        cin>>u>>v>>w;
        G1[u].push_back(node{v,(ll)w});
        G1[v].push_back(node{u,(ll)w});
    }
    for(int i=1,u,v,w;i<n;i++){
        cin>>u>>v>>w;
        G2[u].push_back(node{v,(ll)w});
        G2[v].push_back(node{u,(ll)w});
    }
    dep1[1]=dep2[1]=0;
    dfs2(1,0);
    for(int i=1;i<=n;i++){
        G1[i].push_back(node{200000+i,dep2[i]});
        G1[200000+i].push_back(node{i,dep2[i]});
    }
    dfs3(1,0);
    Build(1,tot,1);
    cout<<ans[1]<<endl;
    int x;ll k;
    while(m--){
        cin>>x>>k;
        dfs4(x,k);
        cout<<ans[1]<<endl;
    }
}

signed main()
{
    ios::sync_with_stdio(false); cin.tie(0),cout.tie(0);
    int T=1;
    //scanf("%d",&T);
    while(T--) solve();
}

 

posted @ 2020-11-16 18:48  Mmasker  阅读(130)  评论(0编辑  收藏  举报