EntropyIncreaser

SDOI2015 寻宝游戏

Nov 17th, 2017
218
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 2.76 KB | None | 0 0
  1. #include <cstdio>
  2.  
  3. #include <set>
  4.  
  5. #define LOG(FMT...) // fprintf(stderr, FMT)
  6.  
  7. using namespace std;
  8.  
  9. typedef long long ll;
  10. typedef set<int>::iterator iter;
  11.  
  12. struct edge {
  13.     int v, w;
  14.     edge* next;
  15. };
  16.  
  17. const int N = 100010;
  18.  
  19. int n, m;
  20. edge* g[N];
  21. int vis[N], dep[N], rev[N];
  22. int prt[N][20];
  23. ll sum[N][20];
  24.  
  25. set<int> st;
  26.  
  27. void add_edge(int u, int v, int w);
  28. void dfs(int u);
  29. ll get_dist(int u, int v);
  30. iter my_next(iter it);
  31. iter my_prev(iter it);
  32.  
  33. int main() {
  34.     int u, v, w;
  35.     iter it;
  36.     ll ans = 0;
  37.     scanf("%d%d", &n, &m);
  38.     for (int rep = 1; rep < n; ++rep) {
  39.         scanf("%d%d%d", &u, &v, &w);
  40.         add_edge(u, v, w);
  41.         add_edge(v, u, w);
  42.     }
  43.     prt[1][0] = 1;
  44.     dfs(1);
  45.     while (m--) {
  46.         scanf("%d", &u);
  47.         if ((it = st.find(vis[u])) == st.end()) {
  48.             it = st.insert(vis[u]).first;
  49.             ans += get_dist(u, rev[*my_next(it)])
  50.                  + get_dist(u, rev[*my_prev(it)])
  51.                  - get_dist(rev[*my_next(it)], rev[*my_prev(it)]);
  52.         } else {
  53.             ans += get_dist(rev[*my_prev(it)], rev[*my_next(it)])
  54.                  - get_dist(u, rev[*my_next(it)])
  55.                  - get_dist(u, rev[*my_prev(it)]);
  56.             LOG("#%d\n", *st.end());
  57.             st.erase(it);
  58.         }
  59.         printf("%lld\n", ans);
  60.     }
  61.     return 0;
  62. }
  63.  
  64. inline iter my_next(iter it) {
  65.     return ++it == st.end() ? st.begin() : it;
  66. }
  67.  
  68. inline iter my_prev(iter it) {
  69.     --it;
  70.     if (it == st.end() && st.size() > 1)
  71.         --it;
  72.     return it;
  73. }
  74.  
  75. inline void add_edge(int u, int v, int w) {
  76.     static edge pool[N << 1];
  77.     static edge* p = pool;
  78.     p->v = v;
  79.     p->w = w;
  80.     p->next = g[u];
  81.     g[u] = p;
  82.     ++p;
  83. }
  84.  
  85. void dfs(int u) {
  86.     static int time;
  87.     vis[u] = ++time;
  88.     rev[time] = u;
  89.     for (int i = 1; i < 20; ++i) {
  90.         prt[u][i] = prt[prt[u][i - 1]][i - 1];
  91.         sum[u][i] = sum[u][i - 1] + sum[prt[u][i - 1]][i - 1];
  92.     }
  93.     for (edge* p = g[u]; p; p = p->next)
  94.         if (!vis[p->v]) {
  95.             prt[p->v][0] = u;
  96.             sum[p->v][0] = p->w;
  97.             dep[p->v] = dep[u] + 1;
  98.             dfs(p->v);
  99.         }
  100. }
  101.  
  102. inline ll get_dist(int u, int v) {
  103.     ll ret = 0;
  104.     LOG("%d %d: ", u, v);
  105.     if (dep[u] < dep[v])
  106.         swap(u, v);
  107.     for (int i = 19; ~i; --i)
  108.         if (dep[prt[u][i]] >= dep[v]) {
  109.             ret += sum[u][i];
  110.             u = prt[u][i];
  111.         }
  112.     if (u == v) {
  113.         LOG("%lld\n", ret);
  114.         return ret;
  115.     }
  116.     for (int i = 19; ~i; --i)
  117.         if (prt[u][i] != prt[v][i]) {
  118.             ret += sum[u][i] + sum[v][i];
  119.             u = prt[u][i];
  120.             v = prt[v][i];
  121.         }
  122.     ret += sum[u][0] + sum[v][0];
  123.     LOG("%lld\n", ret);
  124.     return ret;
  125. }
Advertisement
Add Comment
Please, Sign In to add comment