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

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 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
(1≤T≤500),
indicating the number of test cases. For each test case:

The first line contains two integers n
and D
(1≤n≤100000,1≤D≤109).

The second line contains n
integers p1,p2,…,pn
(0≤pi≤109).

Each of the following n?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 exceed
5×105.

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??为iii到ggg路径上的最大值和最小值.
我们按照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???d≤x?j??,x?i???d≤y?j??,
由于xj≥yjx_j \ge y_jx?j??≥y?j??,
只需要考虑xi?d≤yjx_i -
d \le y_jx?i???d≤y?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

BestCoder 1st Anniversary ($)

Recommend

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

Statistic | Submit | Discuss
| Note

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

时间: 2024-12-28 23:40:14

hdu 5314 Happy King 树点分冶 树状数组的相关文章

hdu 5314 动态树

Happy King Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 262144/262144 K (Java/Others)Total Submission(s): 821    Accepted Submission(s): 179 Problem Description There are n cities and n−1 roads in Byteland, and they form a tree. The citie

poj1741 Tree 树的点分冶

Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 13528   Accepted: 4350 Description Give a tree with n vertices,each edge has a length(positive integer less than 1001). Define dist(u,v)=The min distance between node u and v. Give an

hdu 4267/poj 3468 A Simple Problem with Integers (分状态的树状数组)

A Simple Problem with Integers Time Limit: 5000/1500 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 4283    Accepted Submission(s): 1334 Problem Description Let A1, A2, ... , AN be N elements. You need to deal with

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

HDU 2852 KiKi&#39;s K-Number (树状数组 &amp;&amp; 二分)

题意:给出对容器的总操作次数n, 接下来是这n个操作.这里对于一个容器提供三种操作, 分别是插入.删除和查找.输入0  e表示插入e.输入1  e表示删除e,若元素不存在输出No Elment!.输入2  e  k表示查找比e大且第k大的数, 若不存在则输出Not Find! 分析:这里考虑树状数组做的原因是在第三个操作的时候, 只要我们记录了元素的总数, 那通过求和操作, 便能够高效地知道到底有多少个数比现在求和的这个数要大, 例如 tot - sum(3)就能知道整个集合里面比3大的数到底有

hdu 3333 Turing Tree (树状数组+离线处理+离散化)

Turing Tree Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 3981    Accepted Submission(s): 1349 Problem Description After inventing Turing Tree, 3xian always felt boring when solving problems a

HDU 3861 The King’s Problem(强连通+二分图最小路径覆盖)

HDU 3861 The King's Problem 题目链接 题意:给定一个有向图,求最少划分成几个部分满足下面条件 互相可达的点必须分到一个集合 一个对点(u, v)必须至少有u可达v或者v可达u 一个点只能分到一个集合 思路:先强连通缩点,然后二分图匹配求最小路径覆盖 代码: #include <cstdio> #include <cstring> #include <vector> #include <algorithm> #include <

ZOJ 2334 HDU 1512 Monkey King

题意: 猴子们打架  认识的猴子不会打架  两只猴子打完以后就认识了  A认识B B认识C A也认识C  每次打架由两伙猴子进行  分别选出自己的最高战斗力  在战斗之后两只猴子战斗力减半  给出m次打架  输出打架后这一伙猴子里的最强战斗力 思路: 判断两只猴子是不是一伙的  用到并查集 快速找出一伙猴子中的最强战斗力用到堆  但打完架两伙猴子合并时堆需要nlogn复杂度  因此用左偏树代替堆 代码: #include<cstdio> #include<cstring> #inc

hdu 1556Color the ball (树状数组,更新区间,查询单点)

Color the ball Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 12566    Accepted Submission(s): 6294 Problem Description N个气球排成一排,从左到右依次编号为1,2,3....N.每次给定2个整数a b(a <= b),lele便为骑上他的“小飞鸽"牌电动车从气