#LCT,树状数组#CF1137F Matches Are Not a Child's Play
分析
考虑从删除序列末尾来看,最大值一定在末尾,
然后与次大值之间夹了整条路径的点,降序以此类推
实际上从小到大是每个点到最大点的路径被打通的过程,由此分成若干条实链。
删除序列的位置实际上是到实链底端的距离加上其它实链底端小于该实链底端的实链总长度之和。
考虑维护每个点所处的实链底端的特征值(当变为最大值时,特征值发生改变),可以标记永久化
对于每一种实链用树状数组维护大小,每次修改新建特征值,换根即可。
代码
#include <cstdio>
#include <cctype>
#include <algorithm>
using namespace std;
const int N=200011; struct node{int y,next;}e[N<<1];
int c[N<<1],as[N],et=1,rk[N],n,ext,m,Q;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
void print(int ans){
if (ans>9) print(ans/10);
putchar(ans%10+48);
}
void update(int x,int y){
for (;x<=m;x+=-x&x) c[x]+=y;
}
int query(int x){
int ans=0;
for (;x;x-=-x&x) ans+=c[x];
return ans;
}
struct Splay{
int son[N][2],stac[N],TOP,fat[N],siz[N]; bool rev[N];
bool unroot(int x){return son[fat[x]][0]==x||son[fat[x]][1]==x;}
bool Is_R(int x){return son[fat[x]][1]==x;}
void pup(int x){siz[x]=siz[son[x][0]]+siz[son[x][1]]+1;}
void Rev(int x){swap(son[x][0],son[x][1]),rev[x]^=1;}
void pdown(int x){
if (son[x][0]) rk[son[x][0]]=rk[x];
if (son[x][1]) rk[son[x][1]]=rk[x];
if (rev[x]){
if (son[x][0]) Rev(son[x][0]);
if (son[x][1]) Rev(son[x][1]);
rev[x]=0;
}
}
void rotate(int x){
int Fa=fat[x],FFa=fat[Fa],wh=Is_R(x),t=son[x][wh^1];
if (unroot(Fa)) son[FFa][Is_R(Fa)]=x;
son[x][wh^1]=Fa,son[Fa][wh]=t;
if (t) fat[t]=Fa; fat[Fa]=x,fat[x]=FFa;
pup(Fa),pup(x);
}
void splay(int x){
int y=x; stac[TOP=1]=y;
while (unroot(y)) stac[++TOP]=y=fat[y];
for (;TOP;--TOP) pdown(stac[TOP]);
for (;unroot(x);rotate(x)){
int Fa=fat[x];
if (unroot(Fa)) rotate((Is_R(x)^Is_R(Fa))?x:Fa);
}
}
void Access(int x){
int y=0;
for (;x;x=fat[y=x]){
splay(x);
update(rk[x],siz[son[x][1]]-siz[x]);
son[x][1]=y,pup(x);
}
update(ext,siz[y]);
}
void Make_root(int x){Access(x),splay(x),Rev(x),rk[x]=ext;}
}Tre;
void dfs(int x){
rk[x]=x;
for (int i=as[x];i;i=e[i].next)
if (e[i].y!=Tre.fat[x]){
Tre.fat[e[i].y]=x,dfs(e[i].y);
if (rk[x]<rk[e[i].y])
rk[x]=rk[e[i].y],Tre.son[x][1]=e[i].y;
}
Tre.siz[x]=Tre.siz[Tre.son[x][1]]+1;
}
int main(){
ext=n=iut(),Q=iut(),m=n+Q;
for (int i=1;i<n;++i){
int x=iut(),y=iut();
e[++et]=(node){y,as[x]},as[x]=et;
e[++et]=(node){x,as[y]},as[y]=et;
}
dfs(n);
for (int i=1;i<=n;++i) ++c[rk[i]];
for (int i=n;i;--i)
if (rk[i]==i) update(i,c[i]),c[i]>>=1;
for (int i=1;i<=Q;++i){
char ch=getchar();
while (!isalpha(ch)) ch=getchar();
if (ch=='u') ++ext,Tre.Make_root(iut());
else if (ch=='w'){
int x=iut(); Tre.splay(x);
print(query(rk[x])-Tre.siz[Tre.son[x][0]]);
putchar(10);
}else{
int x=iut(),y=iut(),sx,sy;
Tre.splay(x),sx=Tre.siz[Tre.son[x][1]];
Tre.splay(y),sy=Tre.siz[Tre.son[y][1]];
if (rk[x]!=rk[y]) print(rk[x]<rk[y]?x:y);
else print(sx<sy?x:y);
putchar(10);
}
}
return 0;
}
#LCT,树状数组#CF1137F Matches Are Not a Child's Play的更多相关文章
- [Codeforces1137F]Matches Are Not a Child's Play——LCT+树状数组
题目链接: [Codeforces1137F]Matches Are Not a Child's Play 题目大意: 我们定义一棵树的删除序列为:每一次将树中编号最小的叶子删掉,将该节点编号加入到当 ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- 树状数组 Binary Indexed Tree/Fenwick Tree
2018-03-25 17:29:29 树状数组是一个比较小众的数据结构,主要应用领域是快速的对mutable array进行区间求和. 对于一般的一维情况下的区间和问题,一般有以下两种解法: 1)D ...
- LOJ2831 JOISC2018 道路建设 LCT、树状数组
传送门 题目的操作大概是:求某个点到根的链的逆序对,然后对这条链做区间赋值 求某个点到根的链,就是LCT中的access操作,所以我们每一次把access过后的链打上标记,就可以做到区间赋值了. 计算 ...
- hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点)
hdu 6200 mustedge mustedge(并查集+树状数组 或者 LCT 缩点) 题意: 给一张无向连通图,有两种操作 1 u v 加一条边(u,v) 2 u v 计算u到v路径上桥的个数 ...
- 【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述 给出一棵n个节点的树,每一个节点开始有一个互不相同的颜色,初始根节点为1. 定义一次感染为:将指定的一个节点到根的链上的所有节点染成一种新的颜色,代价为这条链上不同颜色的数目. 现有m次操作 ...
- CF1137F Matches Are Not a Child's Play(LCT思维题)
题目 CF1137F 很有意思的题目 做法 直接考虑带修改的做法,上一次最大值为u,这次修改v,则最大值为v了 我们发现:\(u-v\)这条链会留到最后,序列里的其他元素相对位置不变,这条链会\(u\ ...
- HDU4836 The Query on the Tree(树状数组&&LCA)
由于智力的问题,百度之星完全lu不动..开场看第一题根据题目给的条件我觉得一定是可以构造出来的,题目给的意思颇有鸽巢原理的感觉,于是觉得开场第一题应该就是智力构造题了,想了半个小时,发现完全想不动,于 ...
- 【POJ 3167】Cow Patterns (KMP+树状数组)
Cow Patterns Description A particular subgroup of K (1 <= K <= 25,000) of Farmer John's cows l ...
- Codeforces - 828E DNA Evolution —— 很多棵树状数组
题目链接:http://codeforces.com/contest/828/problem/E E. DNA Evolution time limit per test 2 seconds memo ...
随机推荐
- 统信UOS系统开发笔记(五):安装QtCreator开发IDE中的中文输入环境Fcitx输入法
前言 中文输入法,QtCreator中无法输入中文也是ubuntu中一个常规问题,在国产银河麒麟系统中也有此问题(PS:最终无法结局,用文本自行贴),国产UOS也有此问题,本片要解决此问题,主要是 ...
- typing的中的Optional说明
from typing import Optional def show_count(count: int, singular: str, plural: Optional[str] = None) ...
- 标准运算符替代函数之operator模块
# 官网参考示例地址 https://docs.python.org/zh-cn/3/library/operator.html # operator模块提供了一套与python的内置的运算符对应的高 ...
- 【LeetCode数组#1二分法】二分查找、搜索插入、在排序数组中查找元素的第一个和最后一个位置
二分查找 题目 力扣704题目链接 给定一个 n 个元素有序的(升序)整型数组 nums 和一个目标值 target ,写一个函数搜索 nums 中的 target,如果目标值存在返回下标,否则返回 ...
- STL-bitset模拟实现
#include<time.h> #include<string> #include<vector> #include<iostream> using ...
- opencv库图像基础4绘图-python
opencv库图像基础4绘图-python 1.绘画线条和简单图形 创建颜色字典和一个画布 import cv2 import numpy as np import matplotlib.pyplot ...
- Redis集群Cluster
Redis Cluster 是社区版推出的 Redis 分布式集群解决方案,主要解决 Redis 分布式方面的需求,比如,当遇到单机内存,并发和流量等瓶颈的时候,Redis Cluster 能起到很好 ...
- C++入门编程----C++运算符(8)
什么是运算符 运算符是让程序执行特定的数学或逻辑操作的符号,用来表示针对数据的特定操作,也称之为操作符.C++运算符分别有算术运算符.关系运算符.逻辑运算符.赋值运算符.位运算符.移位运算符.size ...
- vscode 点击 import 的对象 from 带有 @ 不能自动跳转 - 要配置 jsconfig.json
问题 vscode 点击 import 的对象 from 带有 @ 不能自动跳转 - 要配置 jsconfig.json 答案 根目录 创建 jsconfig.json 20220808 更新 inc ...
- SourceTree 合并DEV分支到master
SourceTree 合并DEV分支到master 1 切换到master分支 2 右键dev分支,选择 合并dev至当前分支 3 提交代码