hdu5314 Happy King

树分治。

代码

#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#define LL long long
#define N 300010
using namespace std;
int dp,pre[N],p[N],tt[N],cnt,q[N];
LL c[N],ans;
int n,i,a,b,w[N],vis[N],s[N],tmp,d,tot1,tot2,v[N];
struct g{
    int a,b;
}A[N],B[N];
bool cmp(g x,g y)
{
    return x.b<y.b;
}
void link(int x,int y)
{
    dp++;pre[dp]=p[x];p[x]=dp;tt[dp]=y;
}
int lowbit(int x)
{
    return x&(-x);
}
void cc(int x,int w)
{
    while (x<=n)
    {
        c[x]+=w;
        x=x+lowbit(x);
    }
}
LL getsum(int x)
{
    LL ans=0;
    while (x>0)
    {
        ans=ans+c[x];
        x=x-lowbit(x);
    }
    return ans;
}
void dfs(int x,int fa,int Min,int Max)
{
    int i;
    Min=min(Min,w[x]);
    Max=max(Max,w[x]);
    if (Max-Min<=d)
    {
    tot1++;A[tot1].a=Min;A[tot1].b=Max;
    tot2++;B[tot2]=A[tot1];
	}
	else
	return;
	i=p[x];
    while (i)
    {
        if ((!vis[tt[i]])&&(tt[i]!=fa))
            dfs(tt[i],x,Min,Max);
        i=pre[i];
    }
}
void getroot(int x,int fa,int sum)
{
    int i,flag=0;
    i=p[x];s[x]=1;
    while (i)
    {
        if ((!vis[tt[i]])&&(tt[i]!=fa))
        {
            getroot(tt[i],x,sum);
            s[x]+=s[tt[i]];
            if (s[tt[i]]>sum/2) flag=1;
        }
        i=pre[i];
    }
    if (sum-s[x]>sum/2) flag=1;
    if (!flag) tmp=x;
}
int ef(int x)
{
    int l,r,m;
    l=1;r=n;
    while (l<=r)
    {
        m=(l+r)>>1;
        if (v[m]>x)
        r=m-1;
        else
        l=m+1;
    }
    return r;
}
void work(int x,int sum)
{
    int root,i,ta,tb;
    getroot(x,0,sum);
    root=tmp;
    i=p[root];
    vis[root]=1;
    while (i)
    {
        if (!vis[tt[i]])
        {
            if (s[tt[i]]>s[root])
            work(tt[i],sum-s[root]);
            else
            work(tt[i],s[tt[i]]);
        }
        i=pre[i];
    }

    tot1=1;
    A[tot1].a=w[root];
	A[tot1].b=w[root];
    i=p[root];
    while (i)
    {
        if (!vis[tt[i]])
        {
            tot2=0;
            dfs(tt[i],0,w[root],w[root]);
            sort(B+1,B+1+tot2,cmp);
            cnt=0;
            for (int j=1;j<=tot2;j++)
            {
                ta=ef(B[j].b);
                tb=ef(B[j].b-d-1);
                ans=ans-(getsum(ta)-getsum(tb));
                ta=ef(B[j].a);cnt++;q[cnt]=ta;
                cc(ta,1);
            }

            for (int j=1;j<=cnt;j++)
            cc(q[j],-1);
        }
        i=pre[i];
    }
    sort(A+1,A+1+tot1,cmp);
    cnt=0;
    for (int j=1;j<=tot1;j++)
    {
        ta=ef(A[j].b);
        tb=ef(A[j].b-d-1);
        ans=ans+(getsum(ta)-getsum(tb));
        ta=ef(A[j].a);cnt++;q[cnt]=ta;
        cc(ta,1);
    }
    for (int j=1;j<=cnt;j++)
    cc(q[j],-1);
    vis[root]=0;
}
int main()
{
    int test;
    scanf("%d",&test);
    while (test)
    {
    test--;
    dp=0;
	memset(p,0,sizeof(p));
    scanf("%d%d",&n,&d);
    for (i=1;i<=n;i++)
    {
        scanf("%d",&w[i]);
        v[i]=w[i];
    }
    sort(v+1,v+1+n);
    for (i=1;i<=n-1;i++)
    {
        scanf("%d%d",&a,&b);
        link(a,b);
        link(b,a);
    }
    ans=0;
    work(1,n);
    printf("%I64d\n",ans*2);
    }
}

  

时间: 2024-08-09 02:21:06

hdu5314 Happy King的相关文章

hdu-5314 Happy King

题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: n<=100000,多组数据,所有数据n的总和<=500000: 题解: 来填一填当年挖下的坑: 这个数据范围真是恶意..直接说五组数据不好吗! 考虑这题怎么做,在这场考试那天的前一天,我学习了树分治算法: 然后他就出了,然后我就写了,然后我就写不出来了: 当年的我实在naive: 我翻出了当时交上去的代码,改了好久好久.. 首先这道题的思路比较容易,最直观的就是树的点分治

POJ2728 Desert King

Time Limit: 3000MS   Memory Limit: 65536KB   64bit IO Format: %lld & %llu Description David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his country to bring water to

hdu 5640 King&#39;s Cake(模拟)

Problem Description It is the king's birthday before the military parade . The ministers prepared a rectangle cake of size n×m(1≤n,m≤10000) . The king plans to cut the cake himself. But he has a strange habit of cutting cakes. Each time, he will cut

[SCOI2005]互不侵犯King

1087: [SCOI2005]互不侵犯King Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 4255  Solved: 2458 [Submit][Status][Discuss] Description 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上 左下右上右下八个方向上附近的各一个格子,共8个格子. Input 只有一行,包含两个数N,K ( 1 <=N <=9, 0 <=

01分数规划+prim POJ2728 Desert King

Desert King Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 26009   Accepted: 7219 Description David the Great has just become the king of a desert country. To win the respect of his people, he decided to build channels all over his coun

POJ3682 King Arthur&#39;s Birthday Celebration

King Arthur is an narcissist who intends to spare no coins to celebrate his coming K-th birthday. The luxurious celebration will start on his birthday and King Arthur decides to let fate tell when to stop it. Every day he will toss a coin which has p

hdu_5314_Happy King(树的点分治)

题目链接:hdu_5314_Happy King 题意: 给出一颗n个结点的树,点上有权值: 求点对(x,y)满足x!=y且x到y的路径上最大值与最小值的差<=D: 题解: 还是树的点分治,在统计答案的时候先按到根的最小值排序,然后用最大值减D去找有多少个满足答案. 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 typedef pair<i

codeforces 710A A. King Moves(水题)

题目链接: A. King Moves 题意: 给出king的位置,问有几个可移动的位置; 思路: 水题,没有思路; AC代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <bits/stdc++.h> #include <stack> #include &l

hdu 5641 King&#39;s Phone(暴力模拟题)

Problem Description In a military parade, the King sees lots of new things, including an Andriod Phone. He becomes interested in the pattern lock screen. The pattern interface is a 3×3 square lattice, the three points in the first line are labeled as