码迷,mamicode.com
首页 > 移动开发 > 详细

hdu 5314 Happy King 树点分冶 树状数组

时间:2015-07-31 23:32:33      阅读:269      评论:0      收藏:0      [点我收藏+]

标签:

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 p技术分享i技术分享技术分享.

Soda, the king of Byteland, wants to travel from a city u技术分享 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.
 

Input
There are multiple test cases. The first line of input contains an integer T技术分享 (1T500)技术分享, indicating the number of test cases. For each test case:

The first line contains two integers n技术分享 and D技术分享 (1n100000,1D10技术分享9技术分享)技术分享.

The second line contains n技术分享 integers p技术分享1技术分享,p技术分享2技术分享,,p技术分享n技术分享技术分享 (0p技术分享i技术分享10技术分享9技术分享)技术分享.

Each of the following n?1技术分享 lines describing roads contains two integers u,v技术分享 (1u,vn,uv)技术分享 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 exceed 5×10技术分享5技术分享技术分享.
 

Output
For each test case, output the number of different pairs that can make Soda happy.
 

Sample Input
1 3 3 1 2 3 1 2 2 3
 

Sample Output
6
Hint
If you need a larger stack size, please use #pragma comment(linker, "/STACK:102400000,102400000") and submit your solution using C++.
题意,给出一个树,要求,其中,结点u - v的路径上最大值与最小值相差不超过k的个数。
与上一题是相同的做法。树点分冶

设分治中心为ggg, 我们只需要计算跨过ggg的答案, 其他的可以分治计算.

跨过根的可以容斥做, 没有限制的 - ∑端点落在同一颗子树上的. 上述两个过程是一样的, 于是只考虑没有限制的怎么做.

xi,yix_i,y_ix?i??,y?i??iiiggg路径上的最大值和最小值. 我们按照xix_ix?i??排序, 然后枚举xix_ix?i??必选, 那么前面可选的xj,yj(j<i)x_j, y_j (j < i)x?j??,y?j??(j<i)必须要满足xi?d≤xj,xi?d≤yjx_i - d \le x_j, x_i - d \le y_jx?i???dx?j??,x?i???dy?j??, 由于xj≥yjx_j \ge y_jx?j??y?j??, 只需要考虑xi?d≤yjx_i - d \le y_jx?i???dy?j??. 于是只要枚举xix_ix?i??然后用树状数组统计答案即可. 复杂度是O(nlog2n)O(n \log^2 n)O(nlog?2??n).

#define N 100050
#define M 100005
#define maxn 205
#define MOD 1000000000000000007
struct 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;
}


Source
 

Recommend
hujie   |   We have carefully selected several similar problems for you:  5338 5337 5336 5335 5334 
 

Statistic | Submit | Discuss | Note

版权声明:本文为博主原创文章,未经博主允许不得转载。

hdu 5314 Happy King 树点分冶 树状数组

标签:

原文地址:http://blog.csdn.net/mengzhengnan/article/details/47177055

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!