luogu P1600毎日の愛のランニング|ツリー差+ LCA

タイトル説明

小さなC学生はジョギングは非常に興味深いと思い、ゲームの「実行中の愛の日々」というセクションを作ることにしました。「愛が実行されている毎日は、」タスクのパンチを完了するために、時間に毎日ライン上の選手を必要とするゲームを開発することです。

ゲームマップは、11個のノードNNNおよびn-1N-1N-1ツリーエッジストリップを含むと考えることができ、各エッジは、2つのノードを接続し、任意の2つのノードの存在は、各パスに到達することができます。111からNNNまでの連続した正の整数のツリーノード番号。

ある選手は、MMM sis_isi、エンドポイントtit_itiのための出発点選手のIII。一日の後にパンチタスクを開始するには、最初の000秒での開始点から同時にすべてのプレイヤーは、そのプレイヤーが完了しても、フィニッシュラインへの最短経路に沿って、彼自身の端に向かって第2レート側、中断のないRANを実行するときパンチタスク。(マップが木なので、みんなのパスが一意になるように)

各ノードは、観察者を配置しているので、小さなC、活動ゲームを疑問。ノードオブザーバのJJJは、プレイヤーが最初のプレイヤーが第2の点JJJ wjw_jwjも取っ処理に達した場合に限り、オブザーバーを観察することができ、最初のwjw_jwj秒を選択するためのプレーヤーを観察します。各小さなCオブザーバーはどのように多くの人々を観察します知りたいですか?

注:私たちは、プレイヤーが自分の最後に到達した後、プレイヤーがゲームを終了することを信じて、彼は観察者に観察される前に、いくつかの時間を待つことができませんでした。ノードJJJエンドとしてプレイヤーのために、次のとおりです。彼は秒前最初wjw_jwjの終わりに達した場合、その後、プレイヤーはオブザーバーJJJノードを観察することはできません。彼はwjw_jwj秒の終わりに到達するために発生した場合、ノードJJJオブザーバは選手を観察することができます。

入力形式

最初の行は二つの整数NNNとMMMを持っています。ツリーのノードの数もオブザーバーの数をNNN表しますが、ここで、MMMは選手の数を表します。

次に、n 1N-1N-1ライン毎、及び二つの整数UUUをVVVは、UUUは、エッジがあるノードVVVにノードを表します。

最初の整数はJJJのwjw_jwj、タイミングノードJJJオブザーバ表示され、前記次のラインNNN整数。

二つの整数sis_isi、およびtit_itiの次MMMラインは、プレイヤーの開始点と終了点を表します。

全てのデータに対して、1≤si確実にするために、ti≤n、0≤wj≤n1\当量S_I、T_I \当量のN、0 \当量w_j \当量n1≤si、TI≤n、0≤wj≤n 。

出力フォーマット

NNN整数出力ライン111は、最初のノードは、整数JJJのJJJのオブザーバーはどのように多くの人々を観察することができ表します。


[解説]羅区1600は毎日愛を実行しています

#include<vector>
#include<cstdio>
#include<cstring>
#include<iostream>
using namespace std;
const int N=6e5+10;
inline int read(){
    int x=0; char c=getchar();
    while(c<'0'||c>'9')c=getchar();
    while('0'<=c&&c<='9'){ x=(x<<3)+(x<<1)+(c^48); c=getchar(); }
    return x;
}
int nxt[N<<1],head[N],go[N<<1],tot;
inline void add(int u,int v){nxt[++tot]=head[u],head[u]=tot,go[tot]=v,nxt[++tot]=head[v],head[v]=tot,go[tot]=u;}
int n,m,w[N],f[N][17];
struct node{
    int x,lca,op;
};
vector<node>a[N];
int dep[N];
void deal(int u,int fa){
    dep[u]=dep[fa]+1;
    for(int i=0;i<16;i++)f[u][i+1]=f[f[u][i]][i];
    for(int i=head[u];i;i=nxt[i]){
        int v=go[i];
        if(v==fa)continue;
        f[v][0]=u;
        deal(v,u);
    }
}
#define _ 10000
inline int LCA(int x,int y){
    if(dep[x]<dep[y])swap(x,y);
    for(int i=16;i>=0;i--)if(dep[f[x][i]]>=dep[y])x=f[x][i];
    if(x==y)return x;
    for(int i=16;i>=0;i--)if(f[x][i]!=f[y][i])x=f[x][i],y=f[y][i];
    return f[x][0];
}
int cnt1[N],cnt2[N],ans[N];
vector<int>del1[N],del2[N];
void dfs(int u,int fa){
    int x=cnt1[_+dep[u]+w[u]],y=cnt2[_+w[u]-dep[u]];
    for(int i=head[u];i;i=nxt[i]){
        int v=go[i];
        if(v==fa)continue;
        dfs(v,u);
    }
    for(int i=0;i<a[u].size();i++){
        int x=a[u][i].x,lca=a[u][i].lca;
        if(a[u][i].op){
            cnt1[_+dep[u]]++;
            del1[lca].push_back(dep[u]);
        }
        else {
            cnt2[_+dep[x]-2*dep[lca]]++;
            del2[lca].push_back(dep[x]-2*dep[lca]);
        }
    }
    for(int i=0;i<del1[u].size();i++)cnt1[_+del1[u][i]]--;
    ans[u]=cnt1[_+dep[u]+w[u]]-x+cnt2[_+w[u]-dep[u]]-y;
    for(int i=0;i<del2[u].size();i++)cnt2[_+del2[u][i]]--;
}
signed main(){
    n=read(),m=read();
    for(int i=1;i<n;i++)add(read(),read());
    deal(1,1);
    for(int i=1;i<=n;i++)w[i]=read();
    for(int i=1,x,y,z;i<=m;i++){
        x=read(),y=read();
        z=LCA(x,y);
        a[x].push_back((node){y,z,1});
        a[y].push_back((node){x,z,0});
    }
    dfs(1,0);
    for(int i=1;i<=n;i++)printf("%d ",ans[i]);
    printf("\n");
    return 0;
}

おすすめ

転載: www.cnblogs.com/naruto-mzx/p/12150157.html