LCA+線段樹 NOIP2016 天天愛跑步
天天愛跑步
題目描述
小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。
這個遊戲的地圖可以看作一一棵包含 nnn個結點和 n?1n-1n?1條邊的樹, 每條邊連接兩個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從111到nnn的連續正整數。
現在有mmm個玩家,第iii個玩家的起點為 SiS_iS?i??,終點為 TiT_iT?i?? 。每天打卡任務開始時,所有玩家在第000秒同時從自己的起點出發, 以每秒跑一條邊的速度, 不間斷地沿著最短路徑向著自己的終點跑去, 跑到終點後該玩家就算完成了打卡任務。 (由於地圖是一棵樹, 所以每個人的路徑是唯一的)
小C想知道遊戲的活躍度, 所以在每個結點上都放置了一個觀察員。 在結點jjj的觀察員會選擇在第WjW_jW?j??秒觀察玩家, 一個玩家能被這個觀察員觀察到當且僅當該玩家在第WjW_jW?j??秒也理到達了結點 jjj 。 小C想知道每個觀察員會觀察到多少人?
註意: 我們認為一個玩家到達自己的終點後該玩家就會結束遊戲, 他不能等待一 段時間後再被觀察員觀察到。 即對於把結點jjj作為終點的玩家: 若他在第WjW_jW?j??秒重到達終點,則在結點jjj的觀察員不能觀察到該玩家;若他正好在第WjW_jW?j??秒到達終點,則在結點jjj的觀察員可以觀察到這個玩家。
輸入輸出格式
輸入格式:第一行有兩個整數nnn和mmm 。其中nnn代表樹的結點數量, 同時也是觀察員的數量, mmm代表玩家的數量。
接下來 n?1n- 1n?1行每行兩個整數uuu和 vvv,表示結點 uuu到結點 vvv有一條邊。
接下來一行 nnn個整數,其中第jjj個整數為WjW_jW?j?? , 表示結點jjj出現觀察員的時間。
接下來 mmm行,每行兩個整數SiS_iS?i??,和TiT_iT?i??,表示一個玩家的起點和終點。
對於所有的數據,保證1≤Si,Ti≤n,0≤Wj≤n1\leq S_i,T_i\leq n, 0\leq W_j\leq n1≤S?i??,T?i??≤n,0≤W?j??≤n 。
輸出格式:輸出1行 nnn個整數,第jjj個整數表示結點jjj的觀察員可以觀察到多少人。
輸入輸出樣例
輸入樣例#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號點,Wi=0W_i=0W?i??=0,故只有起點為1號點的玩家才會被觀察到,所以玩家1和玩家2被觀察到,共有2人被觀察到。
對於2號點,沒有玩家在第2秒時在此結點,共0人被觀察到。
對於3號點,沒有玩家在第5秒時在此結點,共0人被觀察到。
對於4號點,玩家1被觀察到,共1人被觀察到。
對於5號點,玩家1被觀察到,共1人被觀察到。
對於6號點,玩家3被觀察到,共1人被觀察到。
【子任務】
每個測試點的數據規模及特點如下表所示。 提示: 數據範圍的個位上的數字可以幫助判斷是哪一種數據類型。
【提示】
如果你的程序需要用到較大的棧空問 (這通常意味著需要較深層數的遞歸), 請務必仔細閱讀選手日錄下的文本當rumung:/stact.p″, 以了解在最終評測時棧空問的限制與在當前工作環境下調整棧空問限制的方法。
在最終評測時,調用棧占用的空間大小不會有單獨的限制,但在我們的工作
環境中默認會有 8 MB 的限制。 這可能會引起函數調用層數較多時, 程序發生
棧溢出崩潰。
我們可以使用一些方法修改調用棧的大小限制。 例如, 在終端中輸入下列命
令 ulimit -s 1048576
此命令的意義是,將調用棧的大小限制修改為 1 GB。
例如,在選手目錄建立如下 sample.cpp 或 sample.pas
將上述源代碼編譯為可執行文件 sample 後,可以在終端中運行如下命令運
行該程序
./sample
如果在沒有使用命令“ ulimit -s 1048576”的情況下運行該程序, sample
會因為棧溢出而崩潰; 如果使用了上述命令後運行該程序,該程序則不會崩潰。
特別地, 當你打開多個終端時, 它們並不會共享該命令, 你需要分別對它們
運行該命令。
請註意, 調用棧占用的空間會計入總空間占用中, 和程序其他部分占用的內
存共同受到內存限制。
此題我在csdn上寫過了,還是比較詳細,貼鏈接
這裏宰貼一份別人的tarjan求LCA的代碼。
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstring> 4 #include <cstdio> 5 #include <cmath> 6 #include <algorithm> 7 #include <ctime> 8 #include <vector> 9 #include <queue> 10 #include <map> 11 #include <set> 12 #include <string> 13 using namespace std; 14 typedef long long LL; 15 const int MAXN = 300011; 16 const int MAXM = 600011; 17 int n,m,ecnt,first[MAXN],next[MAXM],to[MAXM],f[MAXN][20],deep[MAXN],ans[MAXN],val[MAXN],tong[MAXN],MAXD,w[MAXN],num[1000011]; 18 int head[MAXN],tt[MAXM],nn[MAXM],father[MAXN],vis[MAXN]; 19 vector<int>ljh[MAXN],ljh2[MAXN],ljh3[MAXN]; 20 struct node{ int s,t,lca,len;}a[MAXN]; 21 inline int getint(){ 22 int w=0,q=0; char c=getchar(); while((c<‘0‘||c>‘9‘) && c!=‘-‘) c=getchar(); 23 if(c==‘-‘) q=1,c=getchar(); while (c>=‘0‘&&c<=‘9‘) w=w*10+c-‘0‘,c=getchar(); return q?-w:w; 24 } 25 inline void link(int x,int y){ next[++ecnt]=first[x]; first[x]=ecnt; to[ecnt]=y; } 26 inline void LINK(int x,int y){ nn[++ecnt]=head[x]; head[x]=ecnt; tt[ecnt]=y; } 27 inline int find(int x){ if(father[x]!=x) father[x]=find(father[x]); return father[x]; } 28 inline void init(int x,int fa){ 29 father[x]=x; vis[x]=1; 30 for(int i=head[x];i;i=nn[i]) { 31 int v=tt[i]; 32 if(x==a[v].s&&vis[a[v].t]) a[v].lca=find(a[v].t); 33 if(x==a[v].t&&vis[a[v].s]) a[v].lca=find(a[v].s); 34 } 35 for(int i=first[x];i;i=next[i]) { 36 int v=to[i]; if(v==fa) continue; 37 deep[v]=deep[x]+1; init(v,x); father[v]=x; 38 f[v][0]=x; 39 } 40 } 41 42 inline int lca(int x,int y){ 43 if(deep[x]<deep[y]) swap(x,y); int t=0; while((1<<t)<=deep[x]) t++; t--; 44 for(int i=t;i>=0;i--) if(deep[x]-(1<<i)>=deep[y]) x=f[x][i]; if(x==y) return y; 45 for(int i=t;i>=0;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i]; return f[x][0]; 46 } 47 48 inline void dfs(int x,int fa){ 49 int now=w[x]+deep[x],cun; if(now<=MAXD) cun=tong[now]; 50 for(int i=first[x];i;i=next[i]) { 51 int v=to[i]; if(v==fa) continue; 52 dfs(v,x); 53 } 54 tong[deep[x]]+=val[x]; if(now<=MAXD) ans[x]=tong[now]-cun; 55 for(int i=0,ss=ljh[x].size();i<ss;i++) tong[deep[ljh[x][i]]]--; 56 } 57 58 inline void DFS(int x,int fa){ 59 int now=deep[x]-w[x],cun; now+=300000; cun=num[now]; 60 for(int i=first[x];i;i=next[i]) { 61 int v=to[i]; if(v==fa) continue; 62 DFS(v,x); 63 } 64 for(int i=0,ss=ljh2[x].size();i<ss;i++) num[300000+ljh2[x][i]]++; 65 ans[x]+=num[now]-cun; 66 for(int i=0,ss=ljh3[x].size();i<ss;i++) num[300000+ljh3[x][i]]--; 67 } 68 69 inline void work(){ 70 n=getint(); m=getint(); int x,y; for(int i=1;i<n;i++) { x=getint(); y=getint(); link(x,y); link(y,x); } 71 for(int i=1;i<=n;i++) w[i]=getint(); ecnt=0; 72 for(int i=1;i<=m;i++) { a[i].s=getint(),a[i].t=getint(),val[a[i].s]++; LINK(a[i].s,i); LINK(a[i].t,i);} 73 deep[1]=1; init(1,0); for(int i=1;i<=n;i++) MAXD=max(MAXD,deep[i]); 74 for(int j=1;j<=19;j++) for(int i=1;i<=n;i++) f[i][j]=f[f[i][j-1]][j-1]; 75 for(int i=1;i<=m;i++) { 76 a[i].len=deep[a[i].s]+deep[a[i].t]-deep[a[i].lca]*2; 77 ljh[a[i].lca].push_back(a[i].s); 78 } 79 dfs(1,0); 80 for(int i=1;i<=m;i++) { 81 ljh2[a[i].t].push_back(deep[a[i].t]-a[i].len); 82 ljh3[a[i].lca].push_back(deep[a[i].t]-a[i].len); 83 } 84 DFS(1,0); 85 for(int i=1;i<=m;i++) if(deep[a[i].s]-deep[a[i].lca]==w[a[i].lca]) ans[a[i].lca]--; 86 for(int i=1;i<=n;i++) { printf("%d",ans[i]); if(i<n) printf(" "); } 87 } 88 89 int main() 90 { 91 work(); 92 return 0; 93 }
LCA+線段樹 NOIP2016 天天愛跑步