1. 程式人生 > >【NOIP2016】天天愛跑步

【NOIP2016】天天愛跑步

truct ios 多少 個人 img 自己 ret 一行 速度

題目描述

小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。

這個遊戲的地圖可以看作一一棵包含 技術分享個結點和 技術分享條邊的樹, 每條邊連接兩個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從技術分享技術分享的連續正整數。

現在有技術分享個玩家,第技術分享個玩家的起點為 技術分享,終點為 技術分享 。每天打卡任務開始時,所有玩家在第技術分享秒同時從自己的起點出發, 以每秒跑一條邊的速度, 不間斷地沿著最短路徑向著自己的終點跑去, 跑到終點後該玩家就算完成了打卡任務。 (由於地圖是一棵樹, 所以每個人的路徑是唯一的)

小C想知道遊戲的活躍度, 所以在每個結點上都放置了一個觀察員。 在結點技術分享

的觀察員會選擇在第技術分享秒觀察玩家, 一個玩家能被這個觀察員觀察到當且僅當該玩家在第技術分享秒也理到達了結點 技術分享 。 小C想知道每個觀察員會觀察到多少人?

註意: 我們認為一個玩家到達自己的終點後該玩家就會結束遊戲, 他不能等待一 段時間後再被觀察員觀察到。 即對於把結點技術分享作為終點的玩家: 若他在第技術分享秒重到達終點,則在結點技術分享的觀察員不能觀察到該玩家;若他正好在第技術分享秒到達終點,則在結點技術分享的觀察員可以觀察到這個玩家。

輸入輸出格式

輸入格式:

第一行有兩個整數技術分享技術分享 。其中技術分享代表樹的結點數量, 同時也是觀察員的數量, 技術分享代表玩家的數量。

接下來 技術分享行每行兩個整數技術分享技術分享,表示結點 技術分享到結點 技術分享有一條邊。

接下來一行 技術分享個整數,其中第技術分享個整數為技術分享

, 表示結點技術分享出現觀察員的時間。

接下來 技術分享行,每行兩個整數技術分享,和技術分享,表示一個玩家的起點和終點。

對於所有的數據,保證技術分享

輸出格式:

輸出1行 技術分享個整數,第技術分享個整數表示結點技術分享的觀察員可以觀察到多少人。

輸入輸出樣例

輸入樣例#1:
6 3
2 3
1 2 
1 4 
4 5 
4 6 
0 2 5 1 2 3 
1 5 
1 3 
2 6 
輸出樣例#1:
2 0 0 1 1 1 
輸入樣例#2:
5 3 
1 2 
2 3 
2 4 
1 5 
0 1 0 3 0 
3 1 
1 4
5 5 
輸出樣例#2:
1 2 1 0 1 

說明

【樣例1說明】

對於1號點,技術分享,故只有起點為1號點的玩家才會被觀察到,所以玩家1和玩家2被觀察到,共有2人被觀察到。

對於2號點,沒有玩家在第2秒時在此結點,共0人被觀察到。

對於3號點,沒有玩家在第5秒時在此結點,共0人被觀察到。

對於4號點,玩家1被觀察到,共1人被觀察到。

對於5號點,玩家1被觀察到,共1人被觀察到。

對於6號點,玩家3被觀察到,共1人被觀察到。

【子任務】

每個測試點的數據規模及特點如下表所示。 提示: 數據範圍的個位上的數字可以幫助判斷是哪一種數據類型。

技術分享

題解:

這是一道比較有趣的樹上統計題,並沒有什麽高級算法,只是思想巧妙:

用的大概是一種差分思想,是用桶實現的.(即t[i]表示深度為i的點的個數

我們要將跑的過程轉化成 計算對一個點有貢獻的路徑的個數

於是我們可以開始討論.

我們先看一條路徑s-t:

1.先是從下往上(s-lca)跑,如果對一個點i有貢獻僅當deep[i]+w[i]=deep[s]時.

且對於每一個點,deep[i]+w[i]是定值.所以我們把所有路徑的S打上標記,

然後按照dfs序遍歷,如果一個點x有標記就把t[deep[x]]+=mark[x].

然後每一個點都做同樣的操作:ans[x]+=t[deep[i]+w[i]].

2.然後是lca-t,如果滿足L-deep[t]=w[i]-dep[i]時可產生貢獻,同樣在終點t打上++標記,

然後再回溯的回程中就會把t-lca有貢獻的點都統計完 考慮到等式兩邊都有可能產生負數,

於是就把數組偏移一個N,即所有的訪問和標記都+N

3.考慮到子樹之間 和 子樹對父節點以上節點 統計的影響 我們要在lca處打上標記,消除對父節點以上節點的影響

然後進入下一層dfs之前要保存t[i]的值,設為pre,那麽答案就為回溯以後的t[i]-pre.

4.然後調樣例的時候會發現如果lca滿足統計條件會被統計兩次,於是最後的時候需要減掉重復情況

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cmath>
  4 #include<cstring>
  5 #include<vector>
  6 using namespace std;
  7 const int N=319998,P=300001;
  8 int gi(){
  9     int str=0;char ch=getchar();
 10     while(ch>9 || ch<0)ch=getchar();
 11     while(ch>=0 && ch<=9)str=str*10+ch-0,ch=getchar();
 12     return str;
 13 }
 14 vector<int>q1[N],q2[N],q3[N];
 15 int n,m,head[N],w[N],num=0,maxdep=0;
 16 struct Lin{
 17     int next,to;
 18 }a[N*2];
 19 int Head[N],NUM=0;
 20 struct Linn{
 21     int next,to,id;
 22 }e[N*2];
 23 struct Path{
 24     int s,t,dis,lca;
 25 }q[N];
 26 int fa[N],dep[N];bool vis[N];
 27 int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
 28 void init(int x,int y){a[++num].next=head[x];a[num].to=y;head[x]=num;a[++num].next=head[y];a[num].to=x;head[y]=num;}
 29 void init2(int x,int y,int idd){e[++NUM].next=Head[x];e[NUM].to=y;e[NUM].id=idd;Head[x]=NUM;e[++NUM].next=Head[y];e[NUM].to=x,e[NUM].id=idd;Head[y]=NUM;}
 30 void tarjan(int x,int last)
 31 {
 32     int u,v,lca;
 33     vis[x]=true;
 34     if(dep[x]>maxdep)maxdep=dep[x];
 35     for(int i=head[x];i;i=a[i].next)
 36     {
 37         u=a[i].to;
 38         if(u==last)continue;
 39         dep[u]=dep[x]+1;tarjan(u,x);fa[u]=x;
 40     }
 41     for(int i=Head[x];i;i=e[i].next)
 42     {
 43         v=e[i].to;
 44         if(vis[v])
 45         {
 46             lca=find(v);
 47             q[e[i].id].lca=lca;
 48             q[e[i].id].dis=dep[v]+dep[x]-(dep[lca]<<1);
 49         }
 50     }
 51 }
 52 int t[N],ans[N],tt[N*2],mark[N];
 53 void dfs1(int x,int last)
 54 {
 55     int u,now=dep[x]+w[x],pre=0;
 56     if(now<=maxdep)pre=t[now];
 57     for(int i=head[x];i;i=a[i].next){
 58         u=a[i].to;
 59         if(u==last)continue;
 60         dfs1(u,x);
 61     }
 62     t[dep[x]]+=mark[x];
 63     if(now<=maxdep)ans[x]+=t[now]-pre;
 64     int size=q1[x].size();
 65     for(int i=0;i<size;i++)t[q1[x][i]]--;
 66 }
 67 void dfs2(int x,int last)
 68 {
 69     int u,now=w[x]-dep[x]+P,pre=tt[now];
 70     for(int i=head[x];i;i=a[i].next){
 71         u=a[i].to;
 72         if(u==last)continue;
 73         dfs2(u,x);
 74     }
 75     int size=q2[x].size();
 76     for(int i=0;i<size;i++)tt[q2[x][i]]++;
 77     ans[x]+=tt[now]-pre;
 78     size=q3[x].size();
 79     for(int i=0;i<size;i++)tt[q3[x][i]]--;
 80 }
 81 int main()
 82 {
 83     n=gi();m=gi();
 84     int x,y;
 85     for(int i=1;i<n;i++){
 86         x=gi();y=gi();
 87         init(x,y);
 88     } 
 89     for(int i=1;i<=n;i++)w[i]=gi(),fa[i]=i;
 90     for(int i=1;i<=m;i++)
 91     {
 92         q[i].s=gi();q[i].t=gi();
 93         init2(q[i].s,q[i].t,i);
 94     }
 95     dep[1]=1;
 96     tarjan(1,1);
 97     for(int i=1;i<=m;i++)
 98     {
 99         mark[q[i].s]++;
100         q1[q[i].lca].push_back(dep[q[i].s]);
101     }
102     dfs1(1,1);
103     for(int i=1;i<=m;i++)
104     {
105         q2[q[i].t].push_back(q[i].dis-dep[q[i].t]+P);
106         q3[q[i].lca].push_back(q[i].dis-dep[q[i].t]+P);
107     }
108     dfs2(1,1);
109     for(int i=1;i<=m;i++)if(w[q[i].lca]+dep[q[i].lca]==dep[q[i].s])ans[q[i].lca]--;
110     for(int i=1;i<=n;i++)printf("%d ",ans[i]);
111     return 0;
112 }

【NOIP2016】天天愛跑步