LCT - hdu5002 Tree

news/2024/10/22 15:36:55/

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5002


题意:

给一棵树树,提供四种操作

1:删除(x,y)边,添加(a,b)边,保证操作前后都是合法的树

2:修改a--b路径上所有点的权值为x

3:a--b路径上所有点的权值增加d

4:输出a--b路径上的第二大值及出现的次数,这里的第二大指的为严格第二大,即1 1 2 2 3 3 3 的第二大值为2


思路:

算是LCT的模板题,利用LCT的各种操作实现以上功能,这里讲一下怎么删除(x,y)边,因为LCT的基础cut操作只能删除x与x的父结点的连边

changeRoot(x);//调整x为树的根节点
cut(y);//因为x--y边一定存在,x为根,则y的父结点定为x
这题比较麻烦的是维护第二大值,嗯思路是对伸展树每个结点维护第一大数及出现的次数,再维护第二大数及出现的次数,则伸展树的每个结点的第二大值为自身的权值,左儿子的第一,第二大值,右儿子的第一,第二大值这五个数中的严格第二大


代码:

#include <iostream>
#include <string.h>
#include <stdio.h>
#include <algorithm>
using namespace std;const int MAXSIZE = 100010;
const int INF = 0x1FFFFFFF;struct Node{int sz;Node *ch[2], *pnt;bool rt;bool rev;bool ischange;int add;int wei;int fir, firnum, sec, secnum;
};Node nodes[MAXSIZE];
Node *null = &nodes[0];
int ncnt;int sortarr[6][2];
void push_up(Node *x){x->sz = 1 + x->ch[0]->sz + x->ch[1]->sz;if (x->ischange){x->fir = x->wei;x->firnum = x->sz;x->sec = 0;}else{sortarr[0][0] = x->wei, sortarr[0][1] = 1;if (x->ch[0] != null)if (x->ch[0]->ischange)sortarr[1][0] = x->ch[0]->wei + x->ch[0]->add, sortarr[1][1] = x->ch[0]->sz, sortarr[2][1] = 0;elsesortarr[1][0] = x->ch[0]->fir + x->ch[0]->add, sortarr[1][1] = x->ch[0]->firnum,sortarr[2][0] = x->ch[0]->sec + x->ch[0]->add, sortarr[2][1] = x->ch[0]->secnum;else sortarr[1][1] = sortarr[2][1] = 0;if (x->ch[1] != null)if (x->ch[1]->ischange)sortarr[3][0] = x->ch[1]->wei + x->ch[1]->add, sortarr[3][1] = x->ch[1]->sz, sortarr[4][1] = 0;elsesortarr[3][0] = x->ch[1]->fir + x->ch[1]->add, sortarr[3][1] = x->ch[1]->firnum,sortarr[4][0] = x->ch[1]->sec + x->ch[1]->add, sortarr[4][1] = x->ch[1]->secnum;else sortarr[3][1] = sortarr[4][1] = 0;int maximum=0;for (int i=1;i<5;++i)if (sortarr[i][1]!=0 && sortarr[i][0] > sortarr[maximum][0])maximum = i;x->fir = sortarr[maximum][0];x->firnum = 0;for (int i=0;i<5;++i)if (sortarr[i][0] == sortarr[maximum][0])x->firnum += sortarr[i][1], sortarr[i][1] = 0;maximum = 0;for (int i=1;i<5;++i)if (sortarr[maximum][1] == 0 || (sortarr[i][1]!=0 && sortarr[i][0] > sortarr[maximum][0]))maximum = i;if (sortarr[maximum][1] != 0){x->sec = sortarr[maximum][0];x->secnum = 0;for (int i=0;i<5;++i)if (sortarr[i][0] == sortarr[maximum][0])x->secnum += sortarr[i][1];}else x->secnum = 0;}
}void update_change(Node *x, int wei){x->add = 0;x->wei = wei;x->ischange = true;x->fir = wei;x->firnum = x->sz;x->secnum = 0;
}void push_down(Node *x){if (x->ischange){if (x->ch[0] != null) update_change(x->ch[0], x->wei);if (x->ch[1] != null) update_change(x->ch[1], x->wei);x->ischange = false;}if (x->add != 0){if (x->ch[0] != null) x->ch[0]->add += x->add;if (x->ch[1] != null) x->ch[1]->add += x->add;x->wei += x->add;x->add = 0;}if (x->rev){swap(x->ch[0],x->ch[1]);x->ch[0]->rev = !x->ch[0]->rev;x->ch[1]->rev = !x->ch[1]->rev;x->rev = false;}
}void debug(){for (int j=1;j<=7;++j){Node *t = nodes+j;cout<<endl<<j<<endl;cout<<"wei: "<<t->wei<<" "<<"add: "<<t->add<<" "<<"ischange: "<<t->ischange<<" "<<"fir: "<<t->fir<<" "<<"firnum: "<<t->firnum<<" "<<"sec: "<<t->sec<<" "<<"secnum: "<<t->secnum<<" "<<endl<<"parent: "<<t->pnt - null<<" "<<"leftchild: "<<t->ch[0] - null<<" "<<"rightchild: "<<t->ch[1] - null <<" "<<"isrev: "<<t->rev<<" "<<"isroot: "<<t->rt<<endl;}cout<<"---------------------------"<<endl;
}Node* newNode(int wei){Node* t = &nodes[ncnt++];t->sz = 1;t->pnt = t->ch[0] = t->ch[1] = null;t->rt = true;t->wei = wei;t->add = 0;t->ischange = false;t->fir = wei;t->firnum = 1;t->sec = -INF;t->secnum = 0;t->rev = false;return t;
}void init(){ncnt = 1;null->sz = 0;null->pnt = null->ch[0] = null->ch[1] = null;
}void srotate(Node *x, bool d){Node *y = x->pnt;y->ch[!d] = x->ch[d];if (x->ch[d] != null)x->ch[d]->pnt = y;x->pnt = y->pnt;if (!y->rt){if (y == y->pnt->ch[d])y->pnt->ch[d] = x;elsey->pnt->ch[!d] = x;}x->ch[d] = y;y->pnt = x;if (y->rt){y->rt = false;x->rt = true;}push_up(y);
}void pushdownAll(Node *x){if (!x->rt) pushdownAll(x->pnt);push_down(x);
}void splay(Node *x){Node *y;pushdownAll(x);while (!x->rt){y = x->pnt;if (x == y->ch[0]){if (!y->rt && y == y->pnt->ch[0]){srotate(y, true);//push_up(y);}srotate(x, true);}else{if (!y->rt && y == y->pnt->ch[1]){srotate(y, false);//push_up(y);}srotate(x, false);}}push_up(x);
}void access(Node* u){Node *v = null;while (u != null){splay(u);u->ch[1]->rt = true;(u->ch[1] = v)->rt = false;push_up(u);v = u;u = u->pnt;}
}void cut(Node* v) {access(v);splay(v);v->ch[0]->rt = true;v->ch[0]->pnt = null;v->ch[0] = null;push_up(v);
}void changeRoot(Node *x){access(x);splay(x);x->rev = !x->rev;
}void link(Node *v, Node *u){changeRoot(v);v->pnt = u;
}int arr[MAXSIZE];int main(){int total;int n,m;int i,j,k;int a,b,c,d;scanf("%d",&total);for (i=1;i<=total;++i){init();printf("Case #%d:\n",i);scanf("%d %d",&n,&m);for (j=1;j<=n;++j){scanf("%d",arr+j);newNode(arr[j]);}for (j=1;j<n;++j){scanf("%d %d",&a,&b);link(nodes+a, nodes+b);}Node *x,*y;for (j=0;j<m;++j){scanf("%d",&a);//debug();switch (a){case 1:scanf("%d %d %d %d",&a,&b,&c,&d);x = nodes+a; y = nodes+b;changeRoot(x);cut(y);//debug();link(nodes+c, nodes+d);break;case 2:scanf("%d %d %d",&a,&b,&c);x = nodes + a; y = nodes + b;changeRoot(x);access(y);splay(x);x -> ischange = true;x -> wei = c;x -> add = 0;break;case 3:scanf("%d %d %d",&a,&b,&c);x = nodes + a, y = nodes + b;changeRoot(x);access(y);splay(x);x -> add += c;break;case 4:scanf("%d %d",&a,&b);x = nodes + a, y = nodes + b;changeRoot(x);//debug();access(y);splay(x);if (x->secnum == 0) printf("ALL SAME\n");else printf("%d %d\n", x->sec, x->secnum);break;}//debug();}}return 0;
}



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

相关文章

1144: 5002 进制转换

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

hdu5002:Tree (LCT)

题目传送门&#xff1a;http://acm.hdu.edu.cn/showproblem.php?pid5002 题目大意&#xff1a;一开始给你一棵有N个点的树&#xff08;N<10^5&#xff09;&#xff0c;每个点有权值。现在有四种操作&#xff1a;1&#xff1a;x y a b删掉连接x,y的边&#xff0c;并连接a,b…

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;。 输出…