Tree

Time Limit: 1 Sec

Memory Limit: 256 MB

题目连接

http://acm.hust.edu.cn/vjudge/contest/view.action?cid=93850#problem/F

Description

You are given a tree with N nodes which are numbered by integers 1..N. Each node is associated with an integer as the weight.

Your task is to deal with M operations of 4 types:

1.Delete an edge (x, y) from the tree, and then add a new
edge (a, b). We ensure that it still constitutes a tree after adding
the new edge.

2.Given two nodes a and b in the tree, change the weights
of all the nodes on the path connecting node a and b (including node a
and b) to a particular value x.

3.Given two nodes a and b in the tree, increase the
weights of all the nodes on the path connecting node a and b (including
node a and b) by a particular value d.

4.Given two nodes a and b in the tree, compute the second
largest weight on the path connecting node a and b (including node a
and b), and the number of times this weight occurs on the path. Note
that here we need the strict second largest weight. For instance, the
strict second largest weight of {3, 5, 2, 5, 3} is 3.

Input

 The first line contains an integer T (T<=3), which means there are T test cases in the input.

For each test case, the first line contains two integers N
and M (N, M<=10^5). The second line contains N integers, and the
i-th integer is the weight of the i-th node in the tree (their absolute
values are not larger than 10^4).

In next N-1 lines, there are two integers a and b (1<=a, b<=N), which means there exists an edge connecting node a and b.

The next M lines describe the operations you have to deal
with. In each line the first integer is c (1<=c<=4), which
indicates the type of operation.

If c = 1, there are four integers x, y, a, b (1<= x, y, a, b <=N) after c.

If c = 2, there are three integers a, b, x (1<= a, b<=N, |x|<=10^4) after c.

If c = 3, there are three integers a, b, d (1<= a, b<=N, |d|<=10^4) after c.

If c = 4 (it is a query operation), there are two integers a, b (1<= a, b<=N) after c.

All these parameters have the same meaning as described in problem description.

Output

For each test case, first output "Case #x:"" (x means case ID) in a separate line.

For each query operation, output two values: the second
largest weight and the number of times it occurs. If the weights of
nodes on that path are all the same, just output "ALL SAME" (without
quotes).

 

Sample Input

 2 3 2 1 1 2 1 2 1 3 4 1 2 4 2 3 7 7 5 3 2 1 7 3 6 1 2 1 3 3 4 3 5 4 6 4 7 4 2 6 3 4 5 -1 4 5 7 1 3 4 2 4 4 3 6 2 3 6 5 4 3 6

Sample Output

 Case #1: ALL SAME 1 2 Case #2: 3 2 1 1 3 2 ALL SAME

HINT

题意

树上,维护连边,删除边,区间加,区间定值

询问第二大的数是什么,以及有多少个的操作

题解:

LCT模板题

主要是修改pushdown和pushup这两个地方(比较麻烦……

代码:

#include <cstdio>
#include <iostream>
using namespace std;
#define N 300010
const int inf = << ;
typedef pair<int,int>dl;
struct node
{
node *p,*ch[];
int max,rev,val,addv,min;
int max2,ti2,ti1;
int setv;
int size;
}nodes[N],*cur,*null;
int n,m,u,v,w;
node *newnode(int key)
{
cur->p=cur->ch[]=cur->ch[]=null;
cur->max=cur->min=cur->val=key;
cur->max2=cur->min;
cur->ti2=;
cur->ti1=;
cur->rev=;
cur->size=;
cur->setv=-inf;
return cur++;
}
void init()
{
null=nodes;
null->p=null->ch[]=null->ch[]=null;
null->max=null->val=null->max2=-inf;
null->min=inf;
null->ti2=;
null->ti1=;
null->addv=;
null->rev=;
null->setv=-inf;
null->size=;
cur=nodes+;
}
struct dynaminctree
{
bool isroot(node *x)//判根
{
return x==null || x->p->ch[]!=x && x->p->ch[]!=x;
}
void pushup(node *x)
{
x->max = x->val , x->max2 = -inf;x->ti1=;x->ti2 = ;
x->size=; if(x->ch[] != null)
{
x->size += x->ch[]->size;
int mv = x->ch[]->max;
if(mv > x->max)
{
x->max2 = x->max;
x->ti2 = x->ti1;
x->max = mv;
x->ti1 = x->ch[]->ti1;
}
else if(mv == x->max)
{
x->ti1 += x->ch[]->ti1;
}
else if(mv > x->max2)
{
x->max2 = mv;
x->ti2 = x->ch[]->ti1;
}
else if(mv == x->max2)
{
x->ti2 += x->ch[]->ti1;
} mv = x->ch[]->max2;
if(mv != -inf)
{
if(mv > x->max2)
{
x->max2 = mv;
x->ti2 = x->ch[]->ti2;
}
else if(mv == x->max2)
{
x->ti2 += x->ch[]->ti2;
}
}
} //*****************//
if(x->ch[] != null)
{
x->size += x->ch[]->size;
int mv = x->ch[]->max;
if(mv > x->max)
{
x->max2 = x->max;
x->ti2 = x->ti1;
x->max = mv;
x->ti1 = x->ch[]->ti1;
}
else if(mv == x->max)
{
x->ti1 += x->ch[]->ti1;
}
else if(mv > x->max2)
{
x->max2 = mv;
x->ti2 = x->ch[]->ti1;
}
else if(mv == x->max2)
{
x->ti2 += x->ch[]->ti1;
} mv = x->ch[]->max2;
if(mv != -inf)
{
if(mv > x->max2)
{
x->max2 = mv;
x->ti2 = x->ch[]->ti2;
}
else if(mv == x->max2)
{
x->ti2 += x->ch[]->ti2;
}
}
} }
void pushdown(node *x)
{
if(x==null) return;
if(x->rev)
{
x->rev=;
if(x->ch[]!=null) x->ch[]->rev^=;
if(x->ch[]!=null) x->ch[]->rev^=;
swap(x->ch[],x->ch[]);
}
if(x->setv != -inf)
{
if(x->ch[] != null)
{
x->ch[]->max = x->setv , x->ch[]->ti1 = x->ch[]->size;
x->ch[]->max2 = -inf , x->ch[]->ti2 = ;
x->ch[]->setv = x->setv;
x->ch[]->addv = ;
x->ch[]->val = x->setv;
} if(x->ch[] != null)
{
x->ch[]->max = x->setv , x->ch[]->ti1 = x->ch[]->size;
x->ch[]->max2 = -inf , x->ch[]->ti2 = ;
x->ch[]->setv = x->setv;
x->ch[]->addv = ;
x->ch[]->val = x->setv;
}
x->setv = -inf;
} if(x->addv)
{
if(x->ch[] != null)
{
x->ch[]->max += x->addv;
if(x->ch[]->max2 != -inf) x->ch[]->max2 += x->addv;
x->ch[]->addv += x->addv;
x->ch[]->val += x->addv;
} if(x->ch[] != null)
{
x->ch[]->max += x->addv;
if(x->ch[]->max2 != -inf) x->ch[]->max2 += x->addv;
x->ch[]->addv += x->addv;
x->ch[]->val += x->addv;
} x->addv = ;
}
}
void rotate(node *x,int f)
{
if(isroot(x)) return;
node *y=x->p;
y->ch[!f]=x->ch[f];
x->p=y->p;
if(x->ch[f]!=null) x->ch[f]->p=y;
if(y!=null)
{
if(y==y->p->ch[]) y->p->ch[]=x;
else if(y==y->p->ch[]) y->p->ch[]=x;
}
x->ch[f]=y;
y->p=x;
pushup(y);
}
void splay(node *x)
{
static node *sta[N];
int top=;
sta[]=x;
for(node *y=x;!isroot(y);y=y->p)
sta[top++]=y->p;
while (top) pushdown(sta[--top]);
while (!isroot(x))
{
node *y=x->p;
if(isroot(y)) rotate(x,x==y->ch[]);
else
{
int f=y->p->ch[]==y;
if(y->ch[f]==x) rotate(x,!f);
else rotate(y,f);
rotate(x,f);
}
}
pushup(x);
}
node *access(node *u)
{
node *v=null;
while (u!=null)
{
splay(u);
v->p=u;
u->ch[]=v;
pushup(u);
v=u;
u=u->p;
}
return v;
}
node *link(node *u,node *v)//合并
{
access(u);
splay(u);
u->rev=;
u->p=v;
}
node *cut(node *u)//分离
{
access(u);
splay(u);
u->ch[]=u->ch[]->p=null;
pushup(u);
}
void changeroot(node *u)//换根
{
access(u)->rev^=;
}
node *getroot(node *u)//找根
{
access(u);
splay(u);
while (u->p!=null)
{
u=u->p;
}
splay(u);
return u;
}
bool queryuv(node *u,node *v)//判断是否在同一子树
{
while (u->p!=null) u=u->p;
while (v->p!=null) v=v->p;
return u==v;
}
}splay;
int eu[N],ev[N];
int main ()
{
//freopen("in.txt","r",stdin);
int t;scanf("%d",&t);
for(int cas=;cas<=t;cas++)
{
int q;
scanf("%d%d",&n,&q);
init();
for(int i=;i<=n;i++)
{
int a;
scanf("%d",&a);
newnode(a);
}
for(int i=;i<n;i++)
scanf("%d%d",&eu[i],&ev[i]);
for(int i=;i<n;i++)
splay.link(nodes+eu[i],nodes+ev[i]);
printf("Case #%d:\n",cas);
for(int i=;i<=q;i++)
{
scanf("%d",&u);
if(u==)
{
int x,y;
scanf("%d%d",&x,&y);
scanf("%d%d",&u,&v);
splay.changeroot(nodes+x);
splay.cut(nodes+y);
splay.link(nodes+u,nodes+v);
}
else if(u==)
{
scanf("%d%d%d",&u,&v,&w);
splay.changeroot(nodes+u);
splay.access(nodes+v);
node *q=splay.getroot(nodes+v);
q->max=w;
q->val=w;
if(q->max2!=-inf)q->max2=w;
q->setv=w;
}
else if(u==)
{
scanf("%d%d%d",&u,&v,&w);
splay.changeroot(nodes+u);
splay.access(nodes+v);
node *q=splay.getroot(nodes+v);
q->addv+=w;
q->max+=w;
if(q->max2!=-inf)q->max2+=w;
q->val+=w;
}
else
{
scanf("%d%d",&u,&v);
splay.changeroot(nodes+u);
splay.access(nodes+v);
node *q = splay.getroot(nodes+v);
if(q->max2 == -inf) printf("ALL SAME\n");
else printf("%d %d\n",q->max2,q->ti2);
}
}
}
return ;
}

HDU 5002 Tree LCT 区间更新的更多相关文章

  1. HDU 1698 线段树 区间更新求和

    一开始这条链子全都是1 #include<stdio.h> #include<string.h> #include<algorithm> #include<m ...

  2. HDU 4348 主席树区间更新

    To the moon Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total ...

  3. hdu 1698 线段树 区间更新 区间求和

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total ...

  4. HDU(1698),线段树区间更新

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1698 区间更新重点在于懒惰标记. 当你更新的区间就是整个区间的时候,直接sum[rt] = c*(r- ...

  5. HDU 1698 (线段树 区间更新) Just a Hook

    有m个操作,每个操作 X Y Z是将区间[X, Y]中的所有的数全部变为Z,最后询问整个区间所有数之和是多少. 区间更新有一个懒惰标记,set[o] = v,表示这个区间所有的数都是v,只有这个区间被 ...

  6. HDU 5002 Tree(动态树LCT)(2014 ACM/ICPC Asia Regional Anshan Online)

    Problem Description You are given a tree with N nodes which are numbered by integers 1..N. Each node ...

  7. HDU 5002 Tree

    题意: 一棵树  支持删边加边.路径权值加值.路径权值改值.路径求第二大的数字和其个数 思路: LCT的第二题  题意已经把功能都告诉了  比較裸 要注意的是权值加值和改值两个操作的标记下放问题  要 ...

  8. bzoj2631 tree LCT 区间修改,求和

    tree Time Limit: 30 Sec  Memory Limit: 128 MBSubmit: 4962  Solved: 1697[Submit][Status][Discuss] Des ...

  9. HDU 3016 线段树区间更新+spfa

    Man Down Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Su ...

随机推荐

  1. ORACLE-修改当前会话的语言环境

    修改当前会话的语言环境变量参数:ALTER SESSION SET =将语言改为英语: SQL> ALTER SESSION SET NLS_LANGUAGE='AMERICAN';SESSIO ...

  2. 1613. For Fans of Statistics(STL)

    1613 高端的东西 lower_bounder 函数lower_bound()在first和last中的前闭后开区间进行二分查找,返回大于或等于val的第一个元素位置.如果所有元素都小于val,则返 ...

  3. (转载)Let's Play Games!

    第1题  Alice和她的同学Bob通过网上聊天商量明天早晨谁去教室打扫卫生的事,Bob说:“我在桌上放了一枚硬币,你猜一下,是正面朝上还是反面朝上?如果猜对了,我去扫地.如果猜错了,嘿嘿….” Al ...

  4. 如何从Linux源码获知版本信息

    /*************************************************************************** * 如何从Linux源码获知版本信息 * 声明 ...

  5. disabled

    http://blog.csdn.net/dinglang_2009/article/details/6974887 如果把页面viewstate设为disabled 那么 ispost就一直为fal ...

  6. Parallel stepped for loops in .NET C# z

    ; i < ; i += ) public IEnumerable<int> SteppedIntegerList(int startIndex, int endEndex, int ...

  7. MFC菜单、工具栏和状态栏

    菜单:CMenu类 CMenu类的主要成员函数 BOOL LoadMenu(UINT nIDResource); 加载菜单资源,并将其附加到CMenu对象上.参数nIDResource指定了要加载的菜 ...

  8. bzoj 3124 [Sdoi2013]直径(dfs)

    Description 小Q最近学习了一些图论知识.根据课本,有如下定义.树:无回路且连通的无向图,每条边都有正整数的权值来表示其长度.如果一棵树有N个节点,可以证明其有且仅有N-1 条边. 路径:一 ...

  9. NOIP2014 联合权值

    2.联合权值 (link.cpp/c/pas) [问题描述] 无向连通图G有n个点,n-1条边.点从1到n依次编号,编号为i的点的权值为Wi  ,每条边的长度均为1.图上两点(u, v)的距离定义为u ...

  10. KNN算法java实现代码注释

    K近邻算法思想非常简单,总结起来就是根据某种距离度量检测未知数据与已知数据的距离,统计其中距离最近的k个已知数据的类别,以多数投票的形式确定未知数据的类别. 一直想自己实现knn的java实现,但限于 ...