你還夢不夢痛不痛,回憶這麼重你怎麼背得動 ----序言node
當年的戰火硝煙已經漸漸遠去,可仇恨卻在阿凱蒂王子的心中愈來愈深ios
他的叔父三年前謀權篡位,逼宮殺死了他的父王,用鐵血手腕平定了國內全部的不滿佈局
只有他一我的孤身逃了出來,而如今他組織了一隻強大的軍隊,反攻的號角已經吹響ui
大戰一觸即發,做爲他的機智又勇敢的指揮官,你必需要準確及時的完成他佈置的任務spa
這個國家的佈局是一棵樹,每一個城市都是樹上的結點,其中每一個結點上都有軍隊ai(人數) code
樹上的每條邊有邊權wi,表示經過這條邊所須要的時間 blog
當一個城市u受到攻擊時,全部城市的軍隊都會同時向這個城市移動 get
阿凱蒂王子須要知道在時間T內,u城市最多彙集多少人 string
第一行n,m,分別表示城市數目和詢問次數 it
第二行有n個正整數,表示每一個結點軍隊人數ai
如下n-1行每行描述樹上的一條邊的兩個端點u,v和邊權w
如下m行每行一個詢問u,T
表示在時間T內,u城市最多彙集多少人
注意詢問之間相互獨立
輸出m行,每行一個數
表示詢問的答案
5 5
3 7 1 7 4
2 1 9
3 1 6
4 2 5
5 3 1
5 1
4 3
1 1
1 4
4 2
5
7
3
3
7
n<=80000,m<=80000
邊權和軍隊人數均<=1000
先簡化一下題意,給你一棵樹,樹上每一個點都有一個點權,每次詢問和一個點距離小於等於T的全部點的點權和。
考慮動態點分,對於每一個節點,咱們保存兩個vector,a[i][0]表示整棵子樹到這個點的權值和,a[i][1]表示整棵子樹到i的父節點的點權和。
每一個vector中保存兩個參數,len和x,表示距離小於等於len的點權和是多少。
而後用前綴和統計一下x,每次二分len查詢便可。
每次查詢一個數容斥一下就好。
1 //Never forget why you start 2 #include<iostream> 3 #include<cstdio> 4 #include<cstdlib> 5 #include<cstring> 6 #include<cmath> 7 #include<algorithm> 8 #include<vector> 9 #define inf (2147483647) 10 using namespace std; 11 int n,m,a[100005],lim; 12 struct node{ 13 int next,to,dis; 14 }edge[200005]; 15 int head[100005],size; 16 void putin(int from,int to,int dis){ 17 size++; 18 edge[size].next=head[from]; 19 edge[size].to=to; 20 edge[size].dis=dis; 21 head[from]=size; 22 } 23 int fa[100005][20],dis[100005],depth[100005]; 24 void dfs1(int r,int father){ 25 int i; 26 fa[r][0]=father; 27 depth[r]=depth[father]+1; 28 for(i=head[r];i!=-1;i=edge[i].next){ 29 int y=edge[i].to; 30 if(y!=father){ 31 dis[y]=dis[r]+edge[i].dis; 32 dfs1(y,r); 33 } 34 } 35 } 36 void make(){ 37 lim=log(n)/log(2); 38 for(int i=1;i<=lim;i++) 39 for(int j=1;j<=n;j++) 40 fa[j][i]=fa[fa[j][i-1]][i-1]; 41 } 42 int LCA(int x,int y){ 43 if(depth[x]<depth[y])swap(x,y); 44 for(int i=lim;i>=0;i--) 45 if(depth[fa[x][i]]>=depth[y]) 46 x=fa[x][i]; 47 if(x!=y){ 48 for(int i=lim;i>=0;i--) 49 if(fa[x][i]!=fa[y][i]) 50 x=fa[x][i],y=fa[y][i]; 51 x=fa[x][0]; 52 y=fa[y][0]; 53 } 54 return x; 55 } 56 int dist(int x,int y){ 57 int lca=LCA(x,y); 58 return dis[x]+dis[y]-dis[lca]*2; 59 } 60 int vis[100005],cnt[100005],d[100005],root,tot,ff[100005]; 61 void getroot(int r,int father){ 62 int i; 63 cnt[r]=1;d[r]=0; 64 for(i=head[r];i!=-1;i=edge[i].next){ 65 int y=edge[i].to; 66 if(!vis[y]&&y!=father){ 67 getroot(y,r); 68 cnt[r]+=cnt[y]; 69 d[r]=max(d[r],cnt[y]); 70 } 71 } 72 d[r]=max(d[r],tot-cnt[r]); 73 if(d[root]>d[r])root=r; 74 } 75 void buildtree(int r,int father){ 76 int i,all=tot; 77 vis[r]=1; 78 ff[r]=father; 79 for(i=head[r];i!=-1;i=edge[i].next){ 80 int y=edge[i].to; 81 if(!vis[y]){ 82 if(cnt[y]>cnt[r])cnt[y]=all-cnt[r];tot=cnt[y]; 83 root=0;getroot(y,r);buildtree(root,r); 84 } 85 } 86 } 87 struct Ans{ 88 int len,x; 89 }; 90 vector<Ans>ans[100005][2]; 91 bool cmp(const Ans a,const Ans b){ 92 return a.len<b.len; 93 } 94 int upper_bound(int x,int y,int k){ 95 int l=0,r=ans[x][y].size()-1,cnt=0; 96 while(l<=r){ 97 int mid=(l+r)>>1; 98 if(ans[x][y][mid].len<=k)cnt=ans[x][y][mid].x,l=mid+1; 99 else r=mid-1; 100 } 101 return cnt; 102 } 103 void insert(int x,int v){ 104 int i; 105 ans[x][0].push_back((Ans){0,v}); 106 for(i=x;ff[i];i=ff[i]){ 107 int len=dist(x,ff[i]); 108 ans[i][1].push_back((Ans){len,v}); 109 ans[ff[i]][0].push_back((Ans){len,v}); 110 } 111 } 112 int find(int x,int k){ 113 int i,ans=upper_bound(x,0,k); 114 for(i=x;ff[i];i=ff[i]){ 115 int len=dist(x,ff[i]); 116 ans-=upper_bound(i,1,k-len); 117 ans+=upper_bound(ff[i],0,k-len); 118 } 119 return ans; 120 } 121 void clean(){ 122 memset(head,-1,sizeof(head)); 123 size=0; 124 } 125 int main(){ 126 freopen("SS.in","r",stdin); 127 freopen("SS.out","w",stdout); 128 int i,j; 129 clean(); 130 scanf("%d%d",&n,&m); 131 for(i=1;i<=n;i++)scanf("%d",&a[i]); 132 for(i=1;i<n;i++){ 133 int u,v,l; 134 scanf("%d%d%d",&u,&v,&l); 135 putin(u,v,l); 136 putin(v,u,l); 137 } 138 dfs1(1,1);make(); 139 tot=n;root=0;d[0]=inf; 140 getroot(1,0);buildtree(root,0); 141 for(i=1;i<=n;i++)insert(i,a[i]); 142 for(i=1;i<=n;i++){ 143 sort(ans[i][0].begin(),ans[i][0].end(),cmp); 144 sort(ans[i][1].begin(),ans[i][1].end(),cmp); 145 } 146 for(i=1;i<=n;i++){ 147 for(j=1;j<ans[i][0].size();j++) 148 ans[i][0][j].x+=ans[i][0][j-1].x; 149 for(j=1;j<ans[i][1].size();j++) 150 ans[i][1][j].x+=ans[i][1][j-1].x; 151 } 152 while(m--){ 153 int x,k; 154 scanf("%d%d",&x,&k); 155 printf("%d\n",find(x,k)); 156 } 157 return 0; 158 }