码迷,mamicode.com
首页 > 其他好文 > 详细

P3320 [SDOI2015]寻宝游戏

时间:2019-01-20 16:27:41      阅读:163      评论:0      收藏:0      [点我收藏+]

标签:include   cstring   iterator   ase   cto   span   ++   cpp   标记   

题目

P3320 [SDOI2015]寻宝游戏

做法

很巧妙的一种思路,懂了之后觉得大水题

首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历

那就把点丢到\(set\)里面,然后找\(dfs\)的前驱与后继计算路径就好了

其实也有点虚树的思想,只管标记的这几个点

My complete code

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<string>
#include<ctime>
#include<vector>
#include<cmath>
#include<set>
using namespace std;
typedef long long LL;
const LL maxn=1e5+9;
inline LL Read(){
    LL x(0),f(1);char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-1;c=getchar();}
    while(c>='0'&&c<='9')x=(x<<3)+(x<<1)+c-'0',c=getchar();
    return x*f;
}
struct node{
    LL to,next,d;
}dis[maxn<<1];
LL n,T,num,ans,tot;
LL head[maxn],dfn[maxn],pos[maxn],inc[maxn][25],d[maxn],dep[maxn],visit[maxn];
inline void Add(LL u,LL v,LL d){
    dis[++num]=(node){v,head[u],d},head[u]=num;
}
void Dfs(LL u){
    dfn[u]=++tot,pos[tot]=u;
    for(LL i=1;i<=21;++i)
        inc[u][i]=inc[inc[u][i-1]][i-1];
    for(LL i=head[u];i;i=dis[i].next){
        LL v(dis[i].to);
        if(v==inc[u][0])
            continue;
        d[v]=d[u]+dis[i].d,inc[v][0]=u,dep[v]=dep[u]+1;
        Dfs(v);
    }
}
inline LL Lca(LL x,LL y){
    if(dep[x]<dep[y])swap(x,y);
    for(LL i=20;i>=0;--i)
        if(dep[inc[x][i]]>=dep[y])
            x=inc[x][i];
    if(x==y)return x;
    for(LL i=20;i>=0;--i)
        if(inc[x][i]!=inc[y][i])
            x=inc[x][i],y=inc[y][i];
    return inc[x][0];
}
set<LL> Set;
set<LL> :: iterator it,pre,next;
inline void Query(LL x){
    it=Set.find(dfn[x]);
    if(it==Set.begin()){
        pre=Set.end(),--pre;
    }else{
        pre=it,--pre;
    }
    next=it,++next;
    if(next==Set.end())
        next=Set.begin();
    it=Set.find(dfn[x]);
}
inline LL Change(){
    return 2*d[pos[*it]]+d[pos[*next]]+d[pos[*pre]]-2*d[Lca(pos[*pre],pos[*it])]-2*d[Lca(pos[*next],pos[*it])];
}
inline LL Split(){
    return d[pos[*pre]]+d[pos[*next]]-2*d[Lca(pos[*pre],pos[*next])];
}
int main(){
    n=Read(),T=Read();
    for(LL i=1;i<n;++i){
        LL u(Read()),v(Read()),d(Read());
        Add(u,v,d),Add(v,u,d);
    }
    Dfs(1);
    while(T--){
        LL now(Read());
        if(visit[now]){
            Query(now),
            ans-=Change(),ans+=Split(),
            Set.erase(dfn[now]);
        }else{
            Set.insert(dfn[now]),
            Query(now),
            ans-=Split(),ans+=Change();
        }
        visit[now]^=1;
        printf("%lld\n",ans);
    }
    return 0;
}/*
*/

P3320 [SDOI2015]寻宝游戏

标签:include   cstring   iterator   ase   cto   span   ++   cpp   标记   

原文地址:https://www.cnblogs.com/y2823774827y/p/10295225.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!