bzoj3991 sdoi 2015 寻宝游戏

又是一道TA爷A掉的题而我却搞了2个多小时wa好多次,,因为许多低级错误!!!编程的时间也很长,,思路也差
%5思路:按题目中提示的很明显,,从任意点(其实是有效点)出发并回去,,每条有效边都经过两次,,手动模拟一下,,树上操作不就是dfs序没有别的了吗,,其他树上的都是数据结构只有dfs序最万能,,,貌似是dfs序排序后两两之间加起来最后加最后一个到第一个的长度和(还要回去所以,,,),,题目可以出的不那么裸,,因为我就陷进去了,,我想维护一颗虚树却怎么也想不出做法陷进去了,,学习了set的基本用法,把经常写错的LCA重新温习一遍,,思维很重要
知识点:1.树上dfs序 2。虚树 3.set(erase,insert,*–lower_bound(),
*upper_bound()等)取得是值,,
50%:

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<set>
#define N 100000
using namespace std;
typedef long long LL;
struct edge{ int nxt,point,w,v;};
edge e[N<<2+5];
int dfn[N+5],id[N+5],x,l,r,fa[N+5][30],deep[N+5],n,m,cnt,top,inf;
LL dis[N+4];
bool exist[N+5];
set<int>s;
LL ans,d0,d1,d2,d3,d4;
inline void addedge(int u1,int v1,int w1){ 
  e[++cnt].nxt = e[u1].point; e[u1].point = cnt; e[cnt].v = v1; e[cnt].w =w1;} 
inline void insert(int u1,int v1,int w1){ addedge(u1,v1,w1); addedge(v1,u1,w1);};
inline int getnum(){
    char c; int num;
    while (!isdigit(c=getchar()));
    num = c - '0';
    while (isdigit(c=getchar())) num = num*10 + c - '0';
    return num;
}


void init(){
    cnt = 0; top = 0; inf = 1000000000;
    memset(dfn,0,sizeof(dfn));
    memset(fa,0,sizeof(fa));
    memset(dis,0,sizeof(dis));
    int u1,v1,w1;
    n = getnum(); m = getnum();
    for (int i = 1; i < n; ++i){
    u1=getnum(),v1=getnum(),w1=getnum();
     insert(u1,v1,w1);}
}

inline void dfs(int x){
    for (int i = 1; (1<<i)<=n; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
    dfn[x] = ++top; id[top] = x;
    for (int p = e[x].point; p ; p = e[p].nxt) 
      if (!dfn[e[p].v]) {  
      fa[e[p].v][0] = x;
      deep[e[p].v] = deep[x] + 1;
      dis[e[p].v] = dis[x] + e[p].w;
      dfs(e[p].v);}
}

inline int LCA(int u,int v){
    if ( deep[u]<deep[v]) swap(u,v);
    int l = deep[u] - deep[v];
    for (int i = 0; i <= 20; ++i)
      if (l&(1<<i)) u = fa[u][i];
    for (int i = 20; i>=0; --i)
      if (fa[u][i] != fa[v][i]) u = fa[u][i],v = fa[v][i];
    if (u == v) return u;
    return fa[u][0];
}

inline LL pathlong(int x,int y){
    if (y == inf || x==inf) return 0; 
    x = id[x]; y = id[y];
    return dis[x] + dis[y] - 2*dis[LCA(x,y)];}

inline void make1(){
    s.erase(dfn[x]);
    d1 = pathlong(*--s.lower_bound(inf),*s.upper_bound(-inf)); 
    ans = ans-d0+d1-d2-d3+d4;
}

inline void make2(){
    s.insert(dfn[x]);
    d1 = pathlong(*--s.lower_bound(inf),*s.upper_bound(-inf)); 
    ans = ans -d0+d1+d2+d3-d4;
} 

void print(){
    ans  = 0;
    s.clear();
    s.insert(inf); s.insert(-inf);
    memset(exist,0,sizeof(exist));
    for (int i = 1; i <= m; ++i){
        x = getnum();
        l = *--s.lower_bound(dfn[x]),r = *s.upper_bound(dfn[x]);
        d0 = pathlong(*--s.lower_bound(inf),*s.upper_bound(-inf)); 
        d2 = 0; d3 =0; d4 =0;
        if (l != -inf) d2 = pathlong(dfn[x], l);
        if (r != inf ) d3 = pathlong(dfn[x], r);
        if (l !=-inf && r!= inf) d4 = pathlong (l, r);
        if (exist[x]) make1(); else make2();
        exist[x]^=1;
        printf("%lld\n",ans); 
    }
}

int main(){
    init();
    dfs(1);
    print();
    return 0;
} 

你可能感兴趣的:(bzoj3991 sdoi 2015 寻宝游戏)