dfs序(HDU 5296,Annoying problem)

来源:互联网 发布:创新创业网络课答案 编辑:程序博客网 时间:2024/06/05 00:48

HDU 5296,Annoying problem


如果不好模拟,那么可以考虑计算出来。

dfs序配合二分是树上常用的找特殊点的工具。时间戳的记录使得我们可以快速地找到满足范围限制的点。(夹在某两个时间之间的点)


代码:

#include<stdio.h>#include<vector>#include<set>using namespace std;typedef long long ll;const int maxn = 100010;const int maxe = 20;typedef pair<int,int>pii;int n,q;vector<int>G[maxn];vector<int>W[maxn];int in[maxn];int rk[maxn];int tim;int dp[maxn][maxe];int dep[maxn];ll dis[maxn][maxe];set<pii>s;void dfs(int u,int f,int d){    dep[u]=d;    in[u]=++tim;    rk[tim]=u;    dp[u][0]=f;    for(int i=1;(1<<i)<n;i++) dp[u][i]=-1;    for(int i=0;i<(int)G[u].size();i++)    {        int v = G[u][i];        if(v==f) continue;        dis[v][0]=W[u][i];        dfs(v,u,d+1);    }}ll dist(int u,int v){    if(dep[u]<dep[v]) swap(u,v);    int log;    for(log=1;(1<<log)<=dep[u];log++);log--;    ll sum=0;    for(int i=log;i>=0;i--) if(dep[u]-(1<<i)>=dep[v])    {        sum+=dis[u][i];        u=dp[u][i];    }    if(u==v) return sum;    for(int i=log;i>=0;i--) if(dp[u][i]!=-1&&dp[u][i]!=dp[v][i])    {        sum+=dis[u][i];        u=dp[u][i];        sum+=dis[v][i];        v=dp[v][i];    }    sum+=dis[u][0];    sum+=dis[v][0];    return sum;}void solve(){    scanf("%d %d",&n,&q);    for(int i=1;i<=n;i++)    {        G[i].clear();        W[i].clear();    }    tim=0;    for(int i=1;i<n;i++)    {        int u,v,w;        scanf("%d %d %d",&u,&v,&w);        G[u].push_back(v);        W[u].push_back(w);        G[v].push_back(u);        W[v].push_back(w);    }    dfs(1,-1,0);    for(int j=1;(1<<j)<n;j++) for(int i=1;i<=n;i++) if(dp[i][j-1]!=-1)    {        dp[i][j]=dp[dp[i][j-1]][j-1];        dis[i][j]=dis[i][j-1]+dis[dp[i][j-1]][j-1];    }    s.clear();    int x,y;    ll sum=0;    while(q--)    {        scanf("%d %d",&x,&y);        if(x==1)        {            if(s.size()==0)            {                s.insert(make_pair(in[y],y));                puts("0");                continue;            }        }        if(x==2)        {            if(!s.count(make_pair(in[y],y)))            {                printf("%lld\n",sum);                continue;            }            s.erase(make_pair(in[y],y));            if(s.size()<2)            {                sum=0;                puts("0");                continue;            }        }        int u,v;        if(s.size()==0) s.insert(make_pair(in[y],y));        {            set<pii>::iterator it = s.lower_bound(make_pair(in[y],y)),it2;            if(it==s.end()||it==s.begin())            {                u = s.begin()->second;                v = (--s.end())->second;            }            else            {                it2=it;                --it2;                u = it->second;                v = it2->second;            }        }        if(x==1)        {            sum+=(dist(u,y)+dist(v,y)-dist(u,v))/2;            s.insert(make_pair(in[y],y));        }        else sum-=(dist(u,y)+dist(v,y)-dist(u,v))/2;        printf("%lld\n",sum);    }}int main(){    int T;    scanf("%d",&T);    for(int t=1;t<=T;t++)    {        printf("Case #%d:\n",t);        solve();    }    return 0;}


0 0