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 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

/*
hdu 5314 动态树

problem:
给你一个树,求有多少对(u,v)使u->v路径上面的最大值减去最小值不大于limit

solve:
最开始想的是用树链剖分维护最大最小值,结果超时  卒。。
然后看别人说动态树比树链剖分快一点,于是去学习两天动态树,然后用其维护最大最小值 卒。。

感觉没什么思路 - -
后来发现别人维护一个树的size.维持树中的最大最小值的差不大于limit
所以先按照权值排序,用两个指针. 如果 当前值-最左边值(l) > limit,就将l从这个树中除去
然后将当前节点连接到树上面,即判断与其相连的点哪些在树上面(可以用个数组来判断).

大致思路如此,然后就是如何维护size. 首先动态树中的重链是一直变化的,通常我们是用splay来维护重链上面的值,
所以需要outsize来维护哪些不在重链上面的点.
而 重链 和 普通链会在ACCESS的时候发生变化,于是在其过程中维护一下.

参考:http://blog.csdn.net/u013368721/article/details/47086899
hhh-2016-08-21 09:16:05
*/
#pragma comment(linker,"/STACK:124000000,124000000")
#include <algorithm>
#include <iostream>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#define lson  ch[0]
#define rson  ch[1]
#define ll long long
#define clr(a,b) memset(a,b,sizeof(a))
#define key_val ch[ch[root][1]][0]
using namespace std;
const int maxn = 300100;
const int INF = 1e9+10;
ll ans ;
struct Node* null;
struct Node
{
    Node* ch[2] ;
    Node* fa;
    int Size ;
    int Outsize;
    int val,rev;
    void newnode(int v)
    {
        val = v;
        Size = 1 ;
        Outsize = 0;
        fa = ch[0] = ch[1] = null ;
        rev = 0;
    }
    void update_rev()
    {
        if(this == null)
            return ;
        swap(ch[0],ch[1]);
        rev ^= 1;
    }
    void push_up () {
        if(this == null)
            return ;
        Size = ch[0]->Size + 1 + ch[1]->Size + ch[0]->Outsize + ch[1]->Outsize;
//        cout << ch[0]->Size <<" " <<ch[1] <<Size <<endl;
    }

    void push_down()
    {
        if(this == null)
            return ;
        if(rev)
        {
            ch[0]->update_rev();
            ch[1]->update_rev();
            rev = 0;
        }
    }

    void link_child ( Node* to , int d )
    {
        ch[d] = to;
        to->fa = this ;
    }

    int isroot()
    {
        return fa == null || this != fa->ch[0] && this != fa->ch[1] ;
    }
    void down()
    {
        if ( !isroot () ) fa->down () ;
        push_down () ;
    }
    void Rotate ( int d )
    {
        Node* f = fa ;
        Node* ff = fa->fa ;
        f->link_child ( ch[d] , !d ) ;
        if ( !f->isroot () )
        {
            if ( ff->ch[0] == f ) ff->link_child ( this , 0 ) ;
            else ff->link_child ( this , 1 ) ;
        }
        else fa = ff ;
        link_child (f,d) ;
        f->push_up () ;
    }

    void splay ()
    {
        down () ;
        while ( !isroot () ) {
            if ( fa->isroot () ) {
                this == fa->ch[0] ? Rotate ( 1 ) : Rotate ( 0 ) ;
            } else {
                if ( fa == fa->fa->ch[0] ) {
                    this == fa->ch[0] ? fa->Rotate ( 1 ) : Rotate ( 0 ) ;
                    Rotate ( 1 ) ;
                } else {
                    this == fa->ch[1] ? fa->Rotate ( 0 ) : Rotate ( 1 ) ;
                    Rotate ( 0 ) ;
                }
            }
        }
        push_up () ;
    }

    void access()
    {
        Node* now = this ;
        Node* x = null ;
        while ( now != null )
        {
//            cout <<"now:"<< now->val <<" f:" <<x->val <<endl;
            now->splay () ;
            now->Outsize += (now->ch[1]->Size+now->ch[1]->Outsize);
            now->Outsize -= (x->Size + x->Outsize);
            now->link_child ( x , 1 );
            now->push_up () ;
            x = now ;
            now = now->fa ;
        }
        splay() ;
    }

    void make_root()
    {
        access();
        update_rev();
    }

    void cut()
    {
        access();
        ch[0]->fa = null;
        ch[0] = null;
        push_up();
    }
    void cut(Node* to)
    {
        make_root();
        to->cut();
    }

    void link(Node* to)
    {
        make_root();
        to->make_root();
        fa = to;
//        cout << Size <<" " << Outsize <<endl;
        ans += (ll)(to->Size + to->Outsize)*(Size+Outsize);
//        cout << ans  <<endl;
        to->Outsize += (Size + Outsize);
        push_up();
    }
};
Node memory_pool[maxn];
Node* now;
Node* node[maxn];
struct Edge
{
    int to,next;
}edge[maxn << 2];
int head[maxn],tot;
int vis[maxn];
void Clear()
{
    now = memory_pool;
    now->newnode(-INF);
    null = now ++;
    null->Size = 0;
    tot = 0;
    memset(head,-1,sizeof(head));
    memset(vis,0,sizeof(vis));
}

void add_edge(int u,int v)
{
    edge[tot].to = v,edge[tot].next = head[u],head[u] = tot ++;
}
struct Point
{
    int id,v;
}po[maxn];

bool cmp(Point a,Point b)
{
    return a.v < b.v;
}
int main()
{
    int T,n,cas = 1,limit;
    int x,a,b;

//    freopen("in.txt","r",stdin);
    scanf("%d",&T);
    while(T--)
    {
        Clear();
        scanf("%d%d",&n,&limit);
        ans = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&x);
            now->newnode(x);
            node[i] = now++;
            po[i].v = x,po[i].id = i;
        }
        sort(po+1,po+1+n,cmp);
        for(int i = 1; i < n; i++)
        {
            scanf("%d%d",&a,&b);
            add_edge(a,b);
            add_edge(b,a);
        }
        int l= 1;
        for(int i =1;i <= n;i++)
        {
            while(l <= i && po[i].v - po[l].v > limit)
            {
                int u = po[l].id;
                for(int j = head[u];~j;j = edge[j].next)
                {
                    int v = edge[j].to;
                    if(!vis[v])
                        continue;
                    node[u]->cut(node[v]);
                }
                vis[u] = 0;
                ++l;
            }
            int u = po[i].id;
            for(int j = head[u];~j; j = edge[j].next)
            {
//                cout <<edge[j].to <<endl;
                int v = edge[j].to;
                if(!vis[v])
                    continue;
                node[u]->link(node[v]);
            }
            vis[u] = 1;
        }
        printf("%I64d\n",ans*2);
    }
    return 0;
}

  

时间: 2024-11-05 12:34:49

hdu 5314 动态树的相关文章

hdu 5398 动态树LCT

GCD Tree Time Limit: 5000/2500 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 415    Accepted Submission(s): 172 Problem Description Teacher Mai has a graph with n vertices numbered from 1 to n. For every edge(u,v),

hdu 5002 (动态树lct)

Tree Time Limit: 16000/8000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 920    Accepted Submission(s): 388 Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node is a

hdu 4010 动态树 @

kuangbin模板题,看起来十分高大上 1 /* *********************************************** 2 Author :kuangbin 3 Created Time :2013-9-4 0:13:15 4 File Name :HDU4010.cpp 5 ************************************************ */ 6 7 #include <stdio.h> 8 #include <string

HDU 4836 The Query on the Tree lca || 欧拉序列 || 动态树

lca的做法还是很明显的,简单粗暴, 不过不是正解,如果树是长链就会跪,直接变成O(n).. 最后跑的也挺快,出题人还是挺阳光的.. 动态树的解法也是听别人说能ac的,估计就是放在splay上剖分一下,做法还是比较复杂的,,, 来一发lca: #include <stdio.h> #include <iostream> #include <algorithm> #include <sstream> #include <stdlib.h> #inc

HDU 3966 Aragorn&#39;s Story 动态树

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) [Problem Description] Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies w

HDU 4010 Query on The Trees (动态树)(Link-Cut-Tree)

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意; 先给你一棵树,有 \(4\) 种操作: 1.如果 \(x\) 和 \(y\) 不在同一棵树上则在\(x-y\)连边. 2.如果 \(x\) 和 \(y\) 在同一棵树上并且 \(x!=y\) 则把 \(x\) 换为树根并把 \(y\) 和 \(y\) 的父亲分离. 3.如果 \(x\) 和 \(y\) 在同一棵树上则 \(x\) 到 \(y\) 的路径上所有的点权值\(+w\). 4

hdu 4010 Query on The Trees(动态树)

题意:给定一幅图的连接情况,给出每个点的权值,四种操作: 1 x y 连接x.y所在子树: 2 x y 将同一棵树上的x,y分离,形成两棵子树: 3 w x y 将x.y之间路径上的所有点权加w: 4 x y 查询x.y路径上点权的最大值: 动态树学习参考:http://www.cnblogs.com/BLADEVIL/p/3510997.html http://wenku.baidu.com/view/75906f160b4e767f5acfcedb http://m.blog.csdn.ne

动态树学习(留坑)

做了做鞍山网络赛的题,上来就不自量力的去做1006Tree http://acm.hdu.edu.cn/showproblem.php?pid=5002,特征非常明显的动态树.苦调2小时无果.其实还是熟练度不够,否则应该可以慢慢磨出来的.巨不爽,做的再多,比赛搞不出来,等于不会. 决定再学高级数据结构(主要动态树),不知道是第几次重新学了,QTREE系列和那几道历年省选题提交量都已刷屏. 学完,争取把http://www.lydsy.com/JudgeOnline/problem.php?id=

动态树LCT小结

最开始看动态树不知道找了多少资料,总感觉不能完全理解.但其实理解了就是那么一回事...动态树在某种意思上来说跟树链剖分很相似,都是为了解决序列问题,树链剖分由于树的形态是不变的,所以可以通过预处理节点间的关系,将树转化成连续的区间,再加以其它的数据结构,便能以较快的速度处理序列的修改和查询. 而动态树的问题,是包括了树的合并和拆分操作.这个时候,通过预处理实现的静态树的序列算法不能满足我们的要求,于是我们需要一颗‘动态’的树,能在O(logN)的时间复杂度,处理所有操作. Splay实现的Lin