【SDOI2015第1轮第1试】寻宝游戏

#include<cstdio>
#include<set>
using namespace std;
typedef long long LL;

const int N = 1e5;
int top[N + 5] , dfn[N + 5] , rev[N + 5] , fa[N + 5] , size[N + 5] , son[N + 5] , dep[N + 5];
LL dis[N + 5] , ans , now;
int vis[N + 5] , h[N + 5] , n , m , tot = 1 , cnt;
struct node1{
    int to , nxt , w;
}e[(N << 1) + 5];
set<int> list;
set<int>::iterator it;

inline int read()
{
    char ch = getchar();
    int res = 0;
    for(; ch < '0' || ch > '9'; ch = getchar());
    for(; ch >= '0' && ch <= '9'; ch = getchar()) res = (res << 3) + (res << 1) + ch - '0';
    return res;
}

inline void add(int x , int y , int z)
{
    e[++tot].to = y;
    e[tot].w = z;
    e[tot].nxt = h[x];
    h[x] = tot;
}

inline void dfs1(int x , int f , int d)
{
    dep[x] = d;
    dfn[x] = ++cnt;
    rev[cnt] = x;
    fa[x] = f;
    size[x] = 1;
    for(register int i = h[x]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        if (v == f) continue;
        dis[v] = dis[x] + 1LL * e[i].w;
        dfs1(v , x , d + 1);
        size[x] += size[v];
        if (size[v] > size[son[x]]) son[x] = v;
    }
}

inline void dfs2(int x , int f , int t)
{
    top[x] = t;
    if (son[x] > 0) dfs2(son[x] , x , t);
    for(register int i = h[x]; i; i = e[i].nxt)
    {
        int v = e[i].to;
        if (v == f || v == son[x]) continue;
        dfs2(v , x , v);
    }
}

inline int query(int x , int y)
{
    int fx = top[x] , fy = top[y];
    while (fx != fy)
    {
        if (dep[fx] >= dep[fy]) x = fa[fx] , fx = top[x];
        else y = fa[fy] , fy = top[y];
    }
    if (dep[x] <= dep[y]) return x;
    return y;
}

inline LL ask(int x , int y)
{
    return dis[x] + dis[y] - 2 * dis[query(x , y)];
}

int main()
{
//  freopen("寻宝游戏.in" , "r" , stdin);
    n = read() , m = read();
    int x , y , z;
    for(register int i = 1; i < n; i++)
    {
        x = read() , y = read() , z = read();
        add(x , y , z) , add(y , x , z);
    }
    dfs1(1 , 0 , 1) , dfs2(1 , 0 , 1);
    for(register int i = 1; i <= m; i++)
    {
        x = read();
        x = dfn[x];
        if (!vis[rev[x]]) list.insert(x);
        y = rev[(it = list.lower_bound(x)) == list.begin() ? *--list.end() : *--it];
        z = rev[(it = list.upper_bound(x)) == list.end() ? *list.begin() : *it];
        if (vis[rev[x]]) list.erase(x);
        x = rev[x];
        now = ask(y , x) + ask(x , z) - ask(y , z);
        if (!vis[x]) vis[x] = 1 , ans += now;
        else vis[x] = 0 , ans -= now;
        printf("%lld\n" , ans);
    }
}

原文地址:https://www.cnblogs.com/leiyuanze/p/12337082.html

时间: 2024-11-01 09:27:53

【SDOI2015第1轮第1试】寻宝游戏的相关文章

【SDOI2015第1轮第1试】排序

#include<cstdio> #include<iostream> using namespace std; typedef long long LL; const int N = 1 << 13; int n , a[N]; LL ans , fac[13]; inline bool check(int len) { for(register int i = 1; i <= 1 << n - len; i++) if (a[(i - 1) * (

【SDOI2015第1轮第2试】星际战争

#include<cstdio> #include<queue> using namespace std; const int M = 10000; const double inf = 1e18; int n , m , h[505] , cur[505] , dep[505] , s , t , tot = 1; double a[55] , b[55] , ans , Max; struct edge{ int to , nxt; double w; }e[M + 5] ,

【BZOJ3991】[SDOI2015]寻宝游戏 树链的并+set

[BZOJ3991][SDOI2015]寻宝游戏 Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直到找到所有宝物并返回到最初转移到的村庄为止.小B希望评测一下这个游戏的难度,因此他需要知道玩家找到所有宝物需要行走的最短路程.但是这个游戏中宝物经常变化,有时某个村庄中会突

[SDOI2015][BZOJ3991] 寻宝游戏|set|dfs序|虚树|树上倍增LCA

3991: [SDOI2015]寻宝游戏 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 427  Solved: 212[Submit][Status][Discuss] Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直

【BZOJ】【3991】【SDOI2015】寻宝游戏

dfs序 我哭啊……这题在考试的时候(我不是山东的,CH大法吼)没想出来……只写了50分的暴力QAQ 而且苦逼的写的比正解还长……我骗点分容易吗QAQ 骗分做法: 1.$n,m\leq 1000$: 直接找一个关键点做根进行深搜,算出其他关键点都与root连通的最小边权和,再×2 2.一条链的情况:用set维护序列中哪些点选了,然后ans=(sum[tail]-sum[head])*2; 其中sum[i]表示从序列首到第 i 个的边长之和……嗯就是前缀和优化一下= =取首和尾这一段的Len之和

【BZOJ 3991】 [SDOI2015]寻宝游戏

3991: [SDOI2015]寻宝游戏 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 251 Solved: 137 [Submit][Status][Discuss] Description 小B最近正在玩一个寻宝游戏,这个游戏的地图中有N个村庄和N-1条道路,并且任何两个村庄之间有且仅有一条路径可达.游戏开始时,玩家可以任意选择一个村庄,瞬间转移到这个村庄,然后可以任意在地图的道路上行走,若走到某个村庄中有宝物,则视为找到该村庄内的宝物,直

[bzoj3991][SDOI2015]寻宝游戏_树链的并_倍增lca_平衡树set

寻宝游戏 bzoj-3991 SDOI-2015 题目大意:题目链接. 注释:略. 想法:我们发现如果给定了一些点有宝物的话那么答案就是树链的并. 树链的并的求法就是把所有点按照$dfs$序排序然后相加再减去相邻之间的$lca$. 故此我们按照$dfs$序维护一个平衡树. 每次往里插入节点即可. 实时用$lca$更新答案,复杂度$O(nlogn)$. Code: #include <iostream> #include <cstdio> #include <cstring&g

P3320 [SDOI2015]寻宝游戏

题目 P3320 [SDOI2015]寻宝游戏 做法 很巧妙的一种思路,懂了之后觉得大水题 首先要知道:在一棵树上标记一些点,然后从任意一点出发,遍历所有的的最小路径为\(dfs\)序从小到大遍历 那就把点丢到\(set\)里面,然后找\(dfs\)的前驱与后继计算路径就好了 其实也有点虚树的思想,只管标记的这几个点 My complete code #include<cstdio> #include<iostream> #include<algorithm> #inc

异象石/[SDOI2015]寻宝游戏

AcWing 异象石 洛咕 寻宝游戏 题意:Adera是Microsoft应用商店中的一款解谜游戏. 异象石是进入Adera中异时空的引导物,在Adera的异时空中有一张地图. 这张地图上有\(N(N<=1e5)\)个点,有\(N-1\)条双向边把它们连通起来. 起初地图上没有任何异象石,在接下来的\(M(M<=1e5)\)个时刻中,每个时刻会发生以下三种类型的事件之一: 地图的某个点上出现了异象石(已经出现的不会再次出现); 地图某个点上的异象石被摧毁(不会摧毁没有异象石的点); 向玩家询问