luogu P4178 Tree

传送门

板子ex

开始天真的以为把m组询问改成k组询问就行了

但是板子里面的两层循环求方案实在是接受不了

所以套一个树状数组统计答案就行

注意大于k的边权全都不要

Code:

  1 #include<cstdio>
  2 #include<cstring>
  3 #include<algorithm>
  4 #define ms(a,b) memset(a,b,sizeof a)
  5 #define rep(i,a,n) for(int i = a;i <= n;i++)
  6 #define per(i,n,a) for(int i = n;i >= a;i--)
  7 #define inf 2147483647
  8 using namespace std;
  9 typedef long long ll;
 10 #define B puts("GG")
 11 ll read() {
 12     ll as = 0,fu = 1;
 13     char c = getchar();
 14     while(c < '0' || c > '9') {
 15         if(c == '-') fu = -1;
 16         c = getchar();
 17     }
 18     while(c >= '0' && c <= '9') {
 19         as = as * 10 + c - '0';
 20         c = getchar();
 21     }
 22     return as * fu;
 23 }
 24 //head
 25 const int N = 100003;
 26 int n,m,q[N];
 27 int head[N],mo[N<<1],nxt[N<<1],cst[N<<1],cnt;
 28 void addd(int x,int y,int w) {
 29     nxt[++cnt] = head[x],head[x] = cnt;
 30     mo[cnt] = y,cst[cnt] = w;
 31 }
 32 void add(int x,int y) {
 33     int w = read();
 34     if(x^y) addd(x,y,w),addd(y,x,w);
 35 }
 36 
 37 int sze[N];
 38 bool vis[N];
 39 int sum,rt,maxx[N];
 40 void getroot(int x,int f) {
 41     sze[x] = 1,maxx[x] = 0;
 42     for(int i = head[x];i;i = nxt[i]) {
 43         int sn = mo[i];
 44         if(vis[sn] || sn == f) continue;
 45         getroot(sn,x),sze[x] += sze[sn];
 46         maxx[x] = max(maxx[x],sze[sn]);
 47     }
 48     maxx[x] = max(maxx[x],sum - sze[x]);
 49     if(maxx[x] < maxx[rt]) rt = x;
 50 }
 51 
 52 int dis[N],stk[N];
 53 void getdis(int x,int f) {
 54     // if(dis[x] > m) return;
 55     stk[++stk[0]] = dis[x];
 56     for(int i = head[x];i;i = nxt[i]) {
 57         int sn = mo[i];
 58         if(sn == f || vis[sn]) continue;
 59         dis[sn] = dis[x] + cst[i];
 60         getdis(sn,x);
 61     }
 62 }
 63 
 64 int t[N];
 65 #define low(x) ((x) & (-(x)))
 66 void upd(int x,int k) {
 67     if(x <= 0) return;
 68     for(int i = x;i <= m;i += low(i)) t[i] += k;
 69 }
 70 int qry(int x) {
 71     if(x <= 0) return 0;
 72     int sum = 0;
 73     for(int i = x;i;i -= low(i)) sum += t[i];
 74     return sum;
 75 }
 76 
 77 int ans;
 78 int con[N];
 79 void calc(int x) {
 80     for(int i = head[x];i;i = nxt[i]) {
 81         int sn = mo[i];
 82         if(vis[sn]) continue;
 83         stk[0] = 0,dis[sn] = cst[i],getdis(sn,x);
 84         per(j,stk[0],1) ans += qry(m - stk[j]);
 85         per(j,stk[0],1) {
 86             if(stk[j] > m) continue;
 87             con[++con[0]] = stk[j],upd(stk[j],1);
 88             ans++;
 89         }
 90     }
 91     per(i,con[0],1) upd(con[i],-1);
 92 }
 93 
 94 void solve(int x) {
 95     vis[x] = 1,con[0] = 0,calc(x);
 96     for(int i = head[x];i;i = nxt[i]) {
 97         int sn = mo[i];
 98         if(vis[sn]) continue;
 99         sum = sze[sn],maxx[rt = 0] = inf;
100         getroot(sn,sn),solve(rt);
101     }
102 }
103 
104 int main() {
105     n = read();
106     rep(i,2,n) add(read(),read());
107     m = read();
108     sum = n,maxx[rt = 0] = inf;
109     getroot(1,1),solve(rt);
110     printf("%d\n",ans);
111     return 0;
112 }

 

posted @ 2018-12-02 08:04  白怀潇  阅读(136)  评论(0编辑  收藏  举报