树形DP+树状数组 HDU 5877 Weak Pair

 1 //树形DP+树状数组 HDU 5877  Weak Pair
 2 // 思路:用树状数组每次加k/a[i],每个节点ans+=Sum(a[i]) 表示每次加大于等于a[i]的值
 3 // 这道题要离散化
 4
 5 #include <bits/stdc++.h>
 6 using namespace std;
 7 #define LL long long
 8 typedef pair<int,int> pii;
 9 const double inf = 123456789012345.0;
10 const LL MOD =100000000LL;
11 const int N = 2e5+10;
12 const int maxx = 200010;
13 #define clc(a,b) memset(a,b,sizeof(a))
14 const double eps = 1e-7;
15 void fre() {freopen("in.txt","r",stdin);}
16 void freout() {freopen("out.txt","w",stdout);}
17 inline int read() {int x=0,f=1;char ch=getchar();while(ch>‘9‘||ch<‘0‘) {if(ch==‘-‘) f=-1; ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘) {x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
18
19 map<LL,LL> ma;
20 LL a[N];
21 LL c[N],b[N];
22 LL in[N];
23 vector<LL> g[N];
24 LL lowbit(LL x){ return x&(-x);}
25 LL add(LL x,int t){
26     while(x>0){
27        c[x]+=t;
28        x-=lowbit(x);
29     }
30 }
31 LL Sum(LL x){
32     LL sum=0;
33     while(x<maxx){
34         sum+=c[x];
35         x+=lowbit(x);
36     }
37     return sum;
38 }
39
40 LL ans=0;
41 LL n,k;
42 void dfs(LL rt){
43      for(LL i=0;i<(int)g[rt].size();i++){
44          LL v=g[rt][i];
45          ans+=Sum(ma[a[v]]);
46          if(a[v]==0) add(maxx,1);
47          else add(ma[k/a[v]],1);
48          dfs(v);
49          if(a[v]==0) add(maxx,-1);
50          else add(ma[k/a[v]],-1);
51      }
52 }
53 int main(){
54     int T;
55     scanf("%d",&T);
56     while(T--){
57         ma.clear();
58         memset(c,0,sizeof(c));
59         scanf("%I64d%I64d",&n,&k);
60         for(int i=1;i<=n;i++){
61             scanf("%I64d",&a[i]);
62             b[i*2-2]=a[i];
63             if(a[i]!=0) b[i*2-1]=k/a[i];
64             g[i].clear();
65             in[i]=0;
66         }
67         sort(b,b+2*n);
68         int K=unique(b,b+2*n)-b;
69         int cxt=0;
70         for(int i=0;i<K;i++){
71             ma[b[i]]=++cxt;
72         }
73         for(LL i=0;i<n-1;i++){
74             LL u,v;
75             scanf("%I64d%I64d",&u,&v);
76             g[u].push_back(v);
77             in[v]++;
78         }
79         LL rt;
80         for(LL i=1;i<=n;i++){
81             if(in[i]==0){
82                 rt=i;
83                 break;
84             }
85         }
86         ans=0;
87         if(a[rt]==0) add(maxx,1);
88         else add(ma[k/a[rt]],1);
89         dfs(rt);
90         printf("%I64d\n",ans);
91     }
92     return 0;
93 }
时间: 2024-10-05 02:49:24

树形DP+树状数组 HDU 5877 Weak Pair的相关文章

HDU 2227 Find the nondecreasing subsequences (DP+树状数组+离散化)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2227 Find the nondecreasing subsequences                                  Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)                                             

poj 3616 Milking Time dp+树状数组

题意: 给一堆区间,每个区间有开始时间s,结束时间e,和收益w,现在要找一些区间使收益和最大,且区间之间的间隔最小为r. 分析: 这道题用dp做是简单题,用dp+树状数组做是中等题.dp问题的关键是对状态的定义.有两种方法,一:dp[k]表示按开始时间排序到第k个区间能取得的最大收益.二:dp[t]表示在时间t时能获得的最大收益.定义好状态方程就好写了这不再赘述.有趣的是这个时间复杂度.设一共有M个区间,所有区间的最大时间为L,第一种是M^2的,第二种是M*(logL+logM)的,这题M才10

奶牛抗议 DP 树状数组

奶牛抗议 DP 树状数组 USACO的题太猛了 容易想到\(DP\),设\(f[i]\)表示为在第\(i\)位时方案数,转移方程: \[ f[i]=\sum f[j]\;(j< i,sum[i]-sum[j]\ge0) \] \(O(n^2)\)过不了,考虑优化 移项得: \[ f[i]=\sum f[j]\;(j< i,sum[i]\ge sum[j]) \] 这时候我们发现相当于求在\(i\)前面并且前缀和小于\(sum[i]\)的所有和,这就可以用一个树状数组优化了,在树状数组维护下标为

HDU 5877 Weak Pair(弱点对)

HDU 5877 Weak Pair(弱点对) Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Description 题目描述 You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a non-negative value ai is assigned. An ordere

HDU 5877 Weak Pair(树状数组+dfs+离散化)

http://acm.hdu.edu.cn/showproblem.php?pid=5877 题意: 给出一棵树,每个顶点都有权值,现在要你找出满足要求的点对(u,v)数,u是v的祖先并且a[u]*a[v]<=k. 思路: 转化一下,a[v]<=k/a[u],k/a[u]的最大值也就是k/a[v],也就是寻找<=k/a[v]的个数,到这儿,是不是很像树状数组? 我们只需要从根开始dfs,插入到树状数组中,并且查询即可.注意这道题目需要离散化一下. 1 #include <iostr

hdu 5877 Weak Pair dfs序+树状数组+离散化

Weak Pair Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others) Problem Description You are given a rooted tree of N nodes, labeled from 1 to N. To the ith node a non-negative value ai is assigned.An ordered pair of no

HDU 5877 Weak Pair DFS + 树状数组 + 其实不用离散化

http://acm.hdu.edu.cn/listproblem.php?vol=49 给定一颗树,然后对于每一个节点,找到它的任何一个祖先u,如果num[u] * num[v] <= k.则贡献加1 思路:主要的麻烦就是动态修改前缀和了.因为对于每个数字val.则找它祖先的话, <= k / val的数字,都是合法的.所以问题转化成求你现在dfs中保存的数字,有多少个是  <= k / val的,树状数组即可. 问题就是,数字太大了,这不适合树状数组,那么我们把每个数字离散成他们的下

HDU 5542 The Battle of Chibi dp+树状数组

题目:http://acm.hdu.edu.cn/showproblem.php?pid=5542 题意:给你n个数,求其中上升子序列长度为m的个数 可以考虑用dp[i][j]表示以a[i]结尾的长度为j的上升子序列有多少 裸的dp是o(n2m) 所以需要优化 我们可以发现dp的第3维是找比它小的数,那么就可以用树状数组来找 这样就可以降低复杂度 #include<iostream> #include<cstdio> #include<cstring> #include

HDU 2838 (DP+树状数组维护带权排序)

Reference: http://blog.csdn.net/me4546/article/details/6333225 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=2838 题目大意:每头牛有个愤怒值,每次交换相邻两个数进行升序排序,$cost=val_{1}+val_{2}$,求$\min \sum cost_{i}$ 解题思路: 按输入顺序DP: 第i的值val的最小cost=当前数的逆序数个数*val+当前数的逆序数和 相当于每次只