• 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
    ",ans);
    111     return 0;
    112 }
  • 相关阅读:
    剑指offer十二之数值的整数次方
    剑指offer十一之二进制中1的个数
    剑指offer十之矩形覆盖
    剑指offer九之变态跳台阶
    剑指offer八之跳台阶
    程序员的生活观
    程序员,如何远离你的电脑
    生活管理实用技能
    分享共筑 : 伟大的理念
    技术人员,要学会关心别人
  • 原文地址:https://www.cnblogs.com/yuyanjiaB/p/10052142.html
Copyright © 2020-2023  润新知