HDU 4010 LCT

Query on The Trees

Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)

Total Submission(s): 2599    Accepted Submission(s): 1213

Problem Description

We have met so many problems on the tree, so today we will have a query problem on a set of trees.

There are N nodes, each node will have a unique weight Wi. We will have four kinds of operations on it and you should solve them efficiently. Wish you have fun!

Input

There are multiple test cases in our dataset.

For each case, the first line contains only one integer N.(1 ≤ N ≤ 300000) The next N‐1 lines each contains two integers x, y which means there is an edge between them. It also means we will give you one tree initially.

The next line will contains N integers which means the weight Wi of each node. (0 ≤ Wi ≤ 3000)

The next line will contains an integer Q. (1 ≤ Q ≤ 300000) The next Q lines will start with an integer 1, 2, 3 or 4 means the kind of this operation.

1. Given two integer x, y, you should make a new edge between these two node x and y. So after this operation, two trees will be connected to a new one.

2. Given two integer x, y, you should find the tree in the tree set who contain node x, and you should make the node x be the root of this tree, and then you should cut the edge between node y and its parent. So after this operation, a tree will be separate
into two parts.

3. Given three integer w, x, y, for the x, y and all nodes between the path from x to y, you should increase their weight by w.

4. Given two integer x, y, you should check the node weights on the path between x and y, and you should output the maximum weight on it.

Output

For each query you should output the correct answer of it. If you find this query is an illegal operation, you should output ‐1.

You should output a blank line after each test case.

Sample Input

5
1 2
2 4
2 5
1 3
1 2 3 4 5
6
4 2 3
2 1 2
4 2 3
1 3 5
3 2 1 4
4 1 4

Sample Output

3
-1
7

Hint

We define the illegal situation of different operations:
In first operation: if node x and y belong to a same tree, we think it‘s illegal.
In second operation: if x = y or x and y not belong to a same tree, we think it‘s illegal.
In third operation: if x and y not belong to a same tree, we think it‘s illegal.
In fourth operation: if x and y not belong to a same tree, we think it‘s illegal.


 

Source

The 36th ACM/ICPC Asia Regional Dalian Site —— Online
Contest

代码:

/* ***********************************************
Author :rabbit
Created Time :2014/11/1 10:28:39
File Name :4.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <sstream>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <string>
#include <time.h>
#include <math.h>
#include <queue>
#include <stack>
#include <set>
#include <map>
using namespace std;
#define INF 0x3f3f3f3f
#define eps 1e-8
#define pi acos(-1.0)
typedef long long ll;
const int maxn=300300;
struct Node ;
Node *null;
struct Node{
    Node *fa,*ch[2];
    int Max,val,rev,add;
    inline void clear(int _val){
        fa=ch[0]=ch[1]=null;
        val=Max=_val;
        rev=0;
        add=0;
    }
    inline void push_up(){
        Max=max(val,max(ch[0]->Max,ch[1]->Max));
    }
    inline void setc(Node *p,int d){
        ch[d]=p;
        p->fa=this;
    }
    inline bool d(){
        return fa->ch[1]==this;
    }
    inline bool isroot(){
        return fa==null||fa->ch[0]!=this&&fa->ch[1]!=this;
    }
    inline void flip(){
        if(this==null)return;
        swap(ch[0],ch[1]);
        rev^=1;
    }
    inline void update_add(int w){
        if(this==null)return;
        val+=w;
        add+=w;
        Max+=w;
    }
    inline void push_down(){
        if(rev){
            ch[0]->flip();ch[1]->flip();rev=0;
        }
        if(add){
            ch[0]->update_add(add);
            ch[1]->update_add(add);
            add=0;
        }
    }
    inline void go(){
        if(!isroot())fa->go();
        push_down();
    }
    inline void rot(){
        Node *f=fa,*ff=fa->fa;
        int c=d(),cc=fa->d();
        f->setc(ch[!c],c);
        this->setc(f,!c);
        if(ff->ch[cc]==f)ff->setc(this,cc);
        else this->fa=ff;
        f->push_up();
    }
    inline Node *splay(){
        go();
        while(!isroot()){
            if(!fa->isroot())d()==fa->d()?fa->rot():rot();
            rot();
        }
        push_up();
        return this;
    }
    inline Node *access(){
        for(Node *p=this,*q=null;p!=null;q=p,p=p->fa){
            p->splay()->setc(q,1);
            p->push_up();
        }
        return splay();
    }
    inline Node *find_root(){
        Node *x;
        for(x=access();x->push_down(),x->ch[0]!=null;x=x->ch[0]);
        return x;
    }
    void make_root(){
        access()->flip();
    }
    void cut(){
        access();
        ch[0]->fa=null;
        ch[0]=null;
        push_up();
    }
    void cut(Node *x){
        if(this==x||find_root()!=x->find_root())puts("-1");
        else{
            x->make_root();
            cut();
        }
    }
    void link(Node *x){
        if(find_root()==x->find_root())puts("-1");
        else{
            make_root();fa=x;
        }
    }
};
Node pool[maxn],*tail,*node[maxn];
struct Edge{
    int next,to;
}edge[2*maxn];
int head[maxn],tot;
inline void addedge(int u,int v){
    edge[tot].to=v;
    edge[tot].next=head[u];
    head[u]=tot++;
}
void dfs(int u,int pre){
    for(int i=head[u];i!=-1;i=edge[i].next){
        int v=edge[i].to;
        if(v==pre)continue;
        node[v]->fa=node[u];
        dfs(v,u);
    }
}
void ADD(Node *x,Node *y,int w){
    x->access();
    for(x=null;y!=null;x=y,y=y->fa){
        y->splay();
        if(y->fa==null){
            y->ch[1]->update_add(w);
            x->update_add(w);
            y->val+=w;
            y->push_up();
            return;
        }
        y->setc(x,1);
        y->push_up();
    }
}
int ask(Node *x,Node *y){
    x->access();
    for(x=null;y!=null;x=y,y=y->fa){
        y->splay();
        if(y->fa==null)
            return max(y->val,max(y->ch[1]->Max,x->Max));
        y->setc(x,1);
        y->push_up();
    }
}
int main()
{
     //freopen("data.in","r",stdin);
     //freopen("data.out","w",stdout);
     int n;
     while(~scanf("%d",&n)){
         for(int i=1;i<=n;i++)head[i]=-1;tot=0;
         for(int i=1;i<n;i++){
             int u,v;
             scanf("%d%d",&u,&v);
             addedge(u,v);
             addedge(v,u);
         }
         tail=pool;
         null=tail++;
         null->clear(-INF);
         for(int i=1;i<=n;i++){
             node[i]=tail++;
             int v;scanf("%d",&v);
             node[i]->clear(v);
         }
         dfs(1,1);
         int m,op,x,y,w;
         scanf("%d",&m);
         while(m--){
             scanf("%d",&op);
             if(op==1){
                 scanf("%d%d",&x,&y);
                 node[x]->link(node[y]);
             }
             else if(op==2){
                 scanf("%d%d",&x,&y);
                 node[y]->cut(node[x]);
             }
             else if(op==3){
                 scanf("%d%d%d",&w,&x,&y);
                 if(node[x]->find_root()!=node[y]->find_root())puts("-1");
                 else ADD(node[x],node[y],w);
             }
             else{
                 scanf("%d%d",&x,&y);
                 if(node[x]->find_root()!=node[y]->find_root())puts("-1");
                 else printf("%d\n",ask(node[x],node[y]));
             }
         }
         puts("");
     }
     return 0;
}
时间: 2024-11-06 18:56:28

HDU 4010 LCT的相关文章

hdu 4010 Query on the trees LCT

维护一个带点权的无向图森林,支持: 1.删边 2.加边 3.增加某条链所有点的点权 4.求某条链上点权的最大值 大概思路: 前两个需要更改根(即需要翻转标记) 第三个又需要一个标记,第四个每个节点记录该splay中以该节点为根的子树的最大点权. 收获: 1.对于splay前的标记下传可用递归写法, 虽然慢一点,但不容易写错. 2.access的过程中,在边转换完成后要更新节点信息. 3.对于寻找某子树的根,可以一直向上(会途径重边和轻边)找,这样比access+splay快很多,也很好写. 4.

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

Query on The Trees(hdu 4010)

题意: 给出一颗树,有4种操作: 1.如果x和y不在同一棵树上则在xy连边 2.如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离 3.如果x和y在同一棵树上则x到y的路径上所有的点权值+w 4.如果x和y在同一棵树上则输出x到y路径上的最大值 /* 本来一道很水的LCT,结果hdu的提交页面被我刷屏了... 还是too young too simple啊,刚开始不知道多组数据,提交了N次,然后又因为下面的赋值问题提交了N++次. */ #include<cstdio> #i

HDU 4010 Query on The Trees(动态树)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4010 题意:一棵树,四种操作: (1)若x和y不在一棵树上,将x和y连边: (2)若x和y在一棵树上,将x变成树根,将y从x树上分离: (3)若x和y在一棵树上,将x到y路径上的所有值增加det: (4)若x和y在一棵树上,输出x到y路径上的最大值. 思路:1操作用link维护,2操作用cut,34操作先split(x,y),然后对y做tag,并且记录路径的max值. 1 #include<iost

HDU 4010.Query on The Trees 解题报告

题意: 给出一颗树,有4种操作: 1.如果x和y不在同一棵树上则在xy连边 2.如果x和y在同一棵树上并且x!=y则把x换为树根并把y和y的父亲分离 3.如果x和y在同一棵树上则x到y的路径上所有的点权值+w 4.如果x和y在同一棵树上则输出x到y路径上的最大值 动态树入门题: #include <iostream> #include <cstdio> using namespace std; const int MAXN = 333333; struct node { int v

HDU 4010 Query on The Trees

题意: 一棵树  支持合并.分离.路径加权值.路径权值最大值 思路: LCT入门题  也是我的第一道-  代码来源于kuangbin巨巨  我只是整理出自己的风格留作模版- LCT比较好的入门资料是--<QTREE解法的一些研究> LCT基本做法就是先dfs建树  然后根据输入做上述4个操作 对于合并  就是把u转到树根  然后接在v上 对于分离  就是把u转到splay的根  然后切断与左子树的连接 对于路径加值  就是求出lca  然后包含u和v的子树以及lca点进行加值 对于路径求最值 

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

HDU 5052 LCT

Yaoge's maximum profit Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 516    Accepted Submission(s): 150 Problem Description Yaoge likes to eat chicken chops late at night. Yaoge has eaten to