[HZOI 2015]復仇的序幕曲

【題目描述】

你還夢不夢痛不痛,回憶這麼重你怎麼背得動 ----序言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 }
相關文章
相關標籤/搜索