hdu5002:Tree (LCT)

news/2024/10/22 15:41:28/

题目传送门:http://acm.hdu.edu.cn/showproblem.php?pid=5002

题目大意:一开始给你一棵有N个点的树(N<=10^5),每个点有权值。现在有四种操作:1:x y a b删掉连接x,y的边,并连接a,b,保证操作完后还是一棵树;2:a b x 将a到b路径上的点权值全部变为x;3:a b d 将a到b路径上的点权值全部+d;4:a b 询问a到b中路径上第二大的数是多少(注意,是严格的第二大),以及有多少个。如果没有第二大的数,输出“ALL SAME”。操作个数M<=10^5,一个测试点有不超过3组数据。

题目分析:编程一中午,码出动态树。——第一道LCT

这题算是LCT的半裸题吧。前面的操作都很简单,但是我们如何知道一条链上第二大的数有几个呢?我想先求出第二大的数是几,然后搞一棵可持久化线段树之类乱七八糟脑洞大开地维护每一个数在每一条链上出现几次,然后死命想不出来。直到tututu一语惊醒梦中人:在splay的节点处维护一个最大值,以及最大的个数,还有次大值和次大值的个数不就好了吗?合并的时候讨论一下。我这才发现我好像做数据结构题已经做傻了,把问题复杂化QAQ……

然后码了一个中午,最后发现WA的原因竟然是忘了开long long……

CODE:

#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;const int maxn=100100;
const long long oo=11000000000000001LL;
const long long low=-11000000000001LL;
typedef long long LL;struct Tnode;
void Update(Tnode *,Tnode *);
void Add(LL ,Tnode *);
void Change(LL ,Tnode *);struct Tnode
{LL val,max1,max2,change,add;int Size,num1,num2,path_parent;bool flip;Tnode *fa,*son[2];int Get_d() { return fa->son[1]==this; }void Connect(Tnode *P,int d) { (son[d]=P)->fa=this; }void Up(){Size=(son[0]? son[0]->Size:0)+(son[1]? son[1]->Size:0)+1;max1=val,num1=1;max2=-oo,num2=0;if (son[0]) Update(this,son[0]);if (son[1]) Update(this,son[1]);}void Push_down(){if (flip){swap(son[0],son[1]);if (son[0]) son[0]->flip^=1;if (son[1]) son[1]->flip^=1;flip=false;}if (add){if (son[0]) Add(add,son[0]);if (son[1]) Add(add,son[1]);add=0;}if (change<oo){if (son[0]) Change(change,son[0]);if (son[1]) Change(change,son[1]);change=oo;}}
} tree[maxn];void Work(Tnode *x,LL Max,int Num)
{if (Max>x->max1) x->max2=x->max1,x->num2=x->num1,x->max1=Max,x->num1=Num;elseif (Max==x->max1) x->num1+=Num;elseif (Max>x->max2) x->max2=Max,x->num2=Num;else if (Max==x->max2) x->num2+=Num;
}void Update(Tnode *x,Tnode *y)
{Work(x,y->max1,y->num1);Work(x,y->max2,y->num2);
}void Add(LL a,Tnode *y)
{if (y->change<oo) y->change+=a;else y->add+=a;y->val+=a;y->max1+=a;y->max2+=a;
}void Change(LL c,Tnode *y)
{y->val=y->max1=y->change=c;y->add=0LL;y->num1=y->Size;y->max2=-oo;y->num2=0;
}Tnode *Node[maxn];
int cur;int t,n,m;Tnode *New_node(LL v)
{cur++;tree[cur].val=tree[cur].max1=v;tree[cur].Size=tree[cur].num1=1;tree[cur].max2=-oo;tree[cur].num2=0;tree[cur].change=oo;tree[cur].add=tree[cur].path_parent=0;tree[cur].flip=false;tree[cur].fa=tree[cur].son[0]=tree[cur].son[1]=NULL;return tree+cur;
}void Push(Tnode *P)
{if (!P) return;Push(P->fa);P->Push_down();
}void Zig(Tnode *P)
{int d=P->Get_d();Tnode *F=P->fa;if (P->son[!d]) F->Connect(P->son[!d],d);else F->son[d]=NULL;if (F->fa) F->fa->Connect(P,F->Get_d());else P->fa=NULL;F->Up();P->Connect(F,!d);P->path_parent=F->path_parent;F->path_parent=0;
}void Splay(Tnode *P)
{Push(P);while (P->fa){Tnode *F=P->fa;if (F->fa) ( F->Get_d()^P->Get_d() )? Zig(P):Zig(F);Zig(P);}P->Up();
}void Down(int x)
{Splay(Node[x]);if (Node[x]->son[1]) Node[x]->son[1]->fa=NULL,Node[x]->son[1]->path_parent=x;Node[x]->son[1]=NULL;Node[x]->Up();
}void Access(int x)
{Down(x);int y=Node[x]->path_parent;while (y){Down(y);Node[y]->Connect(Node[x],1);Node[y]->Up();Node[x]->path_parent=0;x=y;y=Node[x]->path_parent;}
}void Evert(int x)
{Access(x);Splay(Node[x]);Node[x]->flip^=1;
}void Link(int x,int y)
{Evert(y);Splay(Node[y]);Node[y]->path_parent=x;
}void Cut(int x,int y)
{Evert(x);Access(y);Splay(Node[x]);Node[x]->son[1]->fa=NULL,Node[x]->son[1]->path_parent=0;Node[x]->son[1]=NULL;Node[x]->Up();
}int main()
{freopen("c.in","r",stdin);freopen("c.out","w",stdout);scanf("%d",&t);for (int g=1; g<=t; g++){printf("Case #%d:\n",g);scanf("%d%d",&n,&m);cur=-1;for (int i=1; i<=n; i++){int v;scanf("%d",&v);Node[i]=New_node(v);}for (int i=1; i<n; i++){int u,v;scanf("%d%d",&u,&v);Link(u,v);}for (int i=1; i<=m; i++){int c;scanf("%d",&c);if (c==1){int x,y,a,b;scanf("%d%d%d%d",&x,&y,&a,&b);Cut(x,y);Link(a,b);}if (c==2){int a,b,x;scanf("%d%d%d",&a,&b,&x);Evert(a);Access(b);Splay(Node[a]);Change(x,Node[a]);}if (c==3){int a,b,d;scanf("%d%d%d",&a,&b,&d);Evert(a);Access(b);Splay(Node[a]);Add(d,Node[a]);}if (c==4){int a,b;scanf("%d%d",&a,&b);Evert(a);Access(b);Splay(Node[a]);if (Node[a]->max2<=low) printf("ALL SAME\n");else printf("%I64d %d\n",Node[a]->max2,Node[a]->num2);}}}return 0;
}


http://www.ppmy.cn/news/712762.html

相关文章

P5002 专心OI - 找祖先【题解】

题目链接&#xff1a;P5002 专心OI - 找祖先。 这是一道既和 LCA 有关&#xff0c;又可以称得上和 LCA 没有多少关系的题。 这道题中的数据范围告诉我们&#xff0c;存图要用邻接表&#xff08;矩阵表示很悲伤&#xff09;&#xff0c;所以先把它的代码给码上&#xff1a; /…

InetAddress.getLocalHost().getHostName() took 5002 milliseconds to respond.

1.使用工具 MAC idea mysql 2.错误场景 在启动项目的时候报错&#xff1a; InetAddress.getLocalHost().getHostName() took 5002 milliseconds to respond.3.解决方案 获取本机的主机名称&#xff08;mac电脑&#xff09; 可以使用 hostname命令 hostname 就可以拿到 **…

ias 配置服务器 文件属性,WX5002与Windows IAS配合实现同一SSID不同VLAN功能(即动态mac-vlan功能)的典型配置...

WX5002与Windows IAS配合实现同一SSID不同VLAN功能(即动态mac-vlan功能)的典型配置 适用WX5002版本:Comware Software, Version 5.20, Release 1106P02 一、组网需求 WX5002、WA2110、H3C POE交换机、便携机(安装有11b/g无线网卡)、Windows IAS服务器 二、组网图 WX5002的IP地…

Test5002

解题链接&#xff1a;http://222.197.91.46:2015/study/Test50002.aspx 依然扔进WinHex里&#xff0c;key就在上面 key:SWUN_CTF{picinfor_666}

WeBase快速入门搭建,http://localhost:5002/WeBASE-Front页面打不开,启动后5002端口自动断开

WeBASE-Front 解决方法&#xff1a;先切到fisco节点下&#xff0c;启动相关节点&#xff0c;案例中用到了node0和node1&#xff0c;所以操作如下&#xff1a; cd~ cd fisco/nodes/127.0.0.1 ./start_all.sh#或者单独启动node0和node1&#xff0c;cd node0 && ./start…

5002 进制转换

问题描述&#xff1a; 输入一个十进制数N&#xff0c;将它转换成R进制数输出。 输入&#xff1a; 输入数据包含多个测试实例&#xff0c;每个测试实例包含两个整数N&#xff08;32位整数&#xff09;和R&#xff08;2<R<16&#xff0c;R<>10&#xff09;。 输出…

Jmeter中配置接口请求报5002无权限,但在Postman可以请求

在调接口过程中&#xff0c;有时会遇到Jmeter按照接口文档配置请求接口后&#xff0c;请求不通过&#xff0c;返回5002的错误&#xff0c;这里切换工具到Postman&#xff0c;按原来操作重新配置并执行&#xff0c;发现请求通过了。将postman中的请求头复制出来放到Jmeter的Http…

IIS崩溃(死循环)

现象&#xff1a;站点经常莫名其妙的卡住&#xff0c;无法访问&#xff0c;查看CPU&#xff0c;达到100% 打开服务器管理器->诊断->事件查看器->自定义视图->服务器角色->Web服务器(IIS)&#xff0c;有一大堆的报错&#xff1a; 5002&#xff1a;应用程序池“…