hdu 5314 Happy King 树点分冶 树状数组
来源:互联网 发布:工作备忘录软件 编辑:程序博客网 时间:2024/06/04 17:49
Happy King
Time Limit: 10000/5000 MS (Java/Others) Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 434 Accepted Submission(s): 79
Problem Description
There are n cities and n−1 roads in Byteland, and they form a tree. The cities are numbered 1 through n . The population in i -th city is pi .
Soda, the king of Byteland, wants to travel from a cityu to another city v along the shortest path. Soda would be happy if the difference between the maximum and minimum population among the cities passed is **no larger than**D . So, your task is to tell Soda how many different pairs (u,v) that can make him happy.
Soda, the king of Byteland, wants to travel from a city
Input
There are multiple test cases. The first line of input contains an integerT (1≤T≤500) , indicating the number of test cases. For each test case:
The first line contains two integersn and D (1≤n≤100000,1≤D≤109) .
The second line containsn integers p1,p2,…,pn (0≤pi≤109) .
Each of the followingn−1 lines describing roads contains two integers u,v (1≤u,v≤n,u≠v) meaning that there is a road connecting city u and city v .
It is guaranteed that the total number of vertices in the input doesn't exceed5×105 .
The first line contains two integers
The second line contains
Each of the following
It is guaranteed that the total number of vertices in the input doesn't exceed
Output
For each test case, output the number of different pairs that can make Soda happy.
Sample Input
13 31 2 31 22 3
Sample Output
6HintIf you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
题意,给出一个树,要求,其中,结点u - v的路径上最大值与最小值相差不超过k的个数。
与上一题是相同的做法。树点分冶
设分治中心为g, 我们只需要计算跨过g的答案, 其他的可以分治计算.
跨过根的可以容斥做, 没有限制的 - ∑端点落在同一颗子树上的. 上述两个过程是一样的, 于是只考虑没有限制的怎么做.
令xi,yi为i到g路径上的最大值和最小值. 我们按照xi排序, 然后枚举xi必选, 那么前面可选的xj,yj(j<i)必须要满足xi−d≤xj,xi−d≤yj, 由于xj≥yj, 只需要考虑xi−d≤yj. 于是只要枚举xi然后用树状数组统计答案即可. 复杂度是O(nlog2n).
#define N 100050#define M 100005#define maxn 205#define MOD 1000000000000000007struct TreeNum{ int a[N],n; //树状数组模板 void init(int nn){ n = nn + 1; for(int i = 0;i<=n + 1;i++) a[i] = 0; } int lowbit(int x) { return x & (-x); } void modify(int x,int add)//一维 { while(x<=n) { a[x]+=add; x+=lowbit(x); } } int get_sum(int x) { if(x < 0) return 0; if(x > n) x = n; int ret=0; while(x!=0) { ret+=a[x]; x-=lowbit(x); } return ret; }};int T,n,m,k,u,v,l,center,all,num,nodes[N],dp[N],xx[N],yy[N],pri[N],mymap[N],no;__int64 ans;bool vis[N];vector<pii> p[N];vector<pii> depV;TreeNum mytree;void findRoot(int root,int fa){ nodes[root] = 1;dp[root] = 0; FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ findRoot(g,root); nodes[root] += nodes[g]; dp[root] = max(dp[root],nodes[g]); } } dp[root] = max(dp[root],all - nodes[root]); if(dp[root] < num){ num = dp[root];center = root; }}int getRoot(int root,int sn){ num = INF;all = sn;center = root; findRoot(root,-1); return center;}void getDp(int root,int fa){ nodes[root] = 1; depV.push_back(mp(xx[root],root)); mymap[no++] = yy[root]; FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ xx[g] = max(xx[root],pri[g]); yy[g] = min(yy[root],pri[g]); getDp(g,root); nodes[root] += nodes[g]; } }}int getIndex(int x){ return lower_bound(mymap,mymap + no,x) - mymap;}__int64 cal(int root,bool isfirst){ depV.clear();no = 0; if(isfirst) xx[root] = pri[root],yy[root] = pri[root]; getDp(root,-1); sort(depV.begin(),depV.end()); sort(mymap,mymap + no); no = unique(mymap,mymap + no) - mymap; __int64 sum = 0; mytree.init(no); for(int i = 0;i < depV.size();i++){ int xi = depV[i].first,yi = yy[depV[i].second]; if(xi - yi <= k ){ int goal = getIndex(xi - k); sum += (__int64)(mytree.get_sum(no + 1) - mytree.get_sum(goal)); } mytree.modify(getIndex(yi) + 1,1); } return sum;}void work(int root,int fa){ vis[root] = true; ans += cal(root,true); FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ ans -= cal(g,false); work(getRoot(g,nodes[g]),-1); } }}int main(){ while(S(T)!=EOF) { while(T--){ S2(n,k); ans = 0; FI(n) p[i + 1].clear(),vis[i + 1] = false; FI(n) scan_d(pri[i+1]); FI(n-1){ S2(u,v); p[u].push_back(mp(v,1)); p[v].push_back(mp(u,1)); } work(getRoot(1,n),-1); printf("%I64d\n",ans * 2); } } return 0;}
方法二,由于第一种方法是排序的x,那么y就是无序的,所以要用离散化加树状数组的方法来解决,但,如果换一个思路,排序y,在yi有序的情况下,不需要使用树状数组,只要用个二分找答案就可以了。为什么这样是对的呢,此时,yj < yi 由于,加入数组的都是满足xi - yi <=k的,所以只需要,yj < xi - k,那么,就一定是解了。
这种方法虽然也是n * logn * logn的复杂度,但由于没有使用高级数据结构所以,常数要小很多。
#define N 100050#define M 100005#define maxn 205#define MOD 1000000000000000007int T,n,m,k,u,v,l,center,all,num,nodes[N],dp[N],xx[N],yy[N],pri[N],no;__int64 ans;bool vis[N];vector<pii> p[N];pii mymap[N];void findRoot(int root,int fa){ nodes[root] = 1;dp[root] = 0; FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ findRoot(g,root); nodes[root] += nodes[g]; dp[root] = max(dp[root],nodes[g]); } } dp[root] = max(dp[root],all - nodes[root]); if(dp[root] < num){ num = dp[root];center = root; }}int getRoot(int root,int sn){ num = INF;all = sn;center = root; findRoot(root,-1); return center;}void getDp(int root,int fa){ nodes[root] = 1; xx[root] = max(xx[fa],pri[root]); yy[root] = min(yy[fa],pri[root]); if(xx[root] - yy[root] <= k) mymap[no++] = mp(yy[root],xx[root]); FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ getDp(g,root); nodes[root] += nodes[g]; } }}__int64 cal(int root,bool isfirst){ no = 0; if(isfirst) xx[root] = pri[root],yy[root] = pri[root]; getDp(root,root); sort(mymap,mymap + no); __int64 sum = 0; for(int i = 0;i < no;i++){ sum += (__int64)(i - (lower_bound(mymap,mymap + i,mp(mymap[i].second - k,0)) - mymap)); } return sum;}void work(int root,int fa){ vis[root] = true; ans += cal(root,true); FI(p[root].size()){ int g = p[root][i].first; if(g != fa && !vis[g]){ ans -= cal(g,false); work(getRoot(g,nodes[g]),-1); } }}int main(){ while(S(T)!=EOF) { while(T--){ S2(n,k); ans = 0; FI(n) p[i + 1].clear(),vis[i + 1] = false; FI(n) scan_d(pri[i+1]); FI(n-1){ S2(u,v); p[u].push_back(mp(v,1)); p[v].push_back(mp(u,1)); } work(getRoot(1,n),-1); printf("%I64d\n",ans * 2); } } return 0;}
Source
BestCoder 1st Anniversary ($)
Recommend
hujie | We have carefully selected several similar problems for you: 5338 5337 5336 5335 5334
0 0
- hdu 5314 Happy King 树点分冶 树状数组
- hdu-5314 Happy King
- HDU 5314 Happy King 点分治
- 【HDU】5314 Happy King【动态树(点分治)】
- 【树分治】 HDOJ 5314 Happy King
- HDU5314 Happy King
- HDU 1394 树状数组
- 树状数组 hdu
- hdu 1166 树状数组
- HDU 2838 树状数组
- hdu 2492【树状数组】
- hdu 3015【树状数组】
- hdu 3874 树状数组
- hdu 3874(树状数组)
- hdu 3890 树状数组
- 【树状数组】hdu 2852
- 【树状数组】hdu 4000
- HDU 4046 树状数组
- KMP算法
- html学习笔记
- ShellExecute使用详解
- epoll的两种触发模式
- iOS开发轻松搞定C语言面试—— 算法
- hdu 5314 Happy King 树点分冶 树状数组
- 如何使用Android MediaStore裁剪大图片
- 1022:Train Problem I
- 华为 试题 最小长方形 算法
- 1.PHP站内搜索
- 关于分布式编程的一点说明
- day02_变量_基本数据类型_数据类型的转换_Scanner_20150731
- Android Volley入门到精通:使用Volley加载网络图片(示例,出错代码)
- linux 下tomcat 6 启动出现日志异常