[BZOJ3306] 树
1.数塔2.[洛谷P2014] 选课3.玉蟾宫 (悬线DP)4.MooFest POJ-1990 (树状数组)5.情书密码 (树状数组)6.[SCOI 2009] 迷路 (矩阵快速幂)
7.[BZOJ3306] 树
8.[NOI2002] 荒岛野人9.SHUFFLE 洗牌 (扩展欧几里得+龟速乘)10.[SDOI2009] Bill的挑战 (状压DP)11.P4168 [Violet] 蒲公英 (莫队的强制在线)12.P3667 [USACO17OPEN] Bovine Genomics G (set容器+二分)13.P7903 兜心の顶(构造)14.[BZOJ2720 Violet 5]列队春游(概率期望+组合数学)15.划分大理石(多重背包)16.P5746 [NOI2002] 机器人M号17.苍与红的试炼(数位DP)18.【唐赛】高一小学期219.P10779 BZOJ4316 小 C 的独立集 (仙人掌DP)20.关于求合法括号子序列个数题目
[BZOJ3306] 树
样例输入:
3 7
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1
样例输出:
1
2
3
4
数据范围
分析
这道题如果没有操作换根
那她就是一道板得不能再板的一道板子题
但是
所以这道题她就非常的友[cao]爱[dan]
各种全军覆没↓
由题意
初始rt(root)=1
所以我们以1为根dfs并建立倍增数组
修改点权就是板子 没什么好说的
如果根换成了rt,要查询x子树内的最小值
那么我们需要分情况讨论:
1)若
2)若
3)若
如图↑
当
实际上的图就是↓
此时我们除去
code
Elaina's code
#include<bits/stdc++.h>
using namespace std;
#define int long long
#define inf 0x3f
#define INF 1000000000
#define mst(a,b) memset(a,b,sizeof(a))
#define Elaina 0
#define lid (id<<1)
#define rid (id<<1|1)
const int N = 1000100;
int read(){
int a=0;
char x=getchar();
while(x<'0'||x>'9')x=getchar();
while(x>='0'&&x<='9')a=(a<<3)+(a<<1)+x-48,x=getchar();
return a;
}
int n,m,rt;
int head[N],v[N],xv[N],tot,cnt,in[N],out[N],a[N],dep[N],f[N][30];
struct EDGE{
int nxt,to;
}e[N*2];
struct seg_TREE{
int l,r,minn;
}tr[N*4];
void build(int id,int l,int r){
tr[id].l=l;
tr[id].r=r;
if(l==r){
tr[id].minn=xv[l];
return;
}
int mid=(l+r)>>1;
build(lid,l,mid);
build(rid,mid+1,r);
tr[id].minn=min(tr[lid].minn,tr[rid].minn);
}
void changemin(int id,int x,int k){
if(tr[id].l==tr[id].r){
tr[id].minn=k;
return;
}
int m=(tr[id].l+tr[id].r)>>1;
if(x<=m)
changemin(lid,x,k);
else
changemin(rid,x,k);
tr[id].minn=min(tr[lid].minn,tr[rid].minn);
return;
}
int askmin(int id,int l,int r){
if(l>r){
return INF;
}
if(tr[id].l>=l&&tr[id].r<=r){
return tr[id].minn;
}
int mid=(tr[id].l+tr[id].r)>>1;
if(r<=mid){
return askmin(lid,l,r);
}
if(l>mid){
return askmin(rid,l,r);
}else{
return min(askmin(lid,l,mid),askmin(rid,mid+1,r));
}
}
void add_1(int u,int v){
e[++tot].to=v;
e[tot].nxt=head[u];
head[u]=tot;
}
void dfs(int x,int fa){
xv[++cnt]=a[x];
in[x]=cnt;
dep[x]=dep[fa]+1;
f[x][0]=fa;
for(int i=head[x];i;i=e[i].nxt){
int k=e[i].to;
if(k!=fa){
dfs(k,x);
}
}
out[x]=cnt;
}
signed main(){
n=read(),m=read();
int x,y;
for(int i=1;i<=n;i++){
x=read(),a[i]=read();
add_1(x,i);
}
rt=1;
dep[0]=0;
dfs(rt,0);
for(int j=1;j<30;j++){
for(int i=1;i<=n;i++)
f[i][j]=f[f[i][j-1]][j-1];
}
// printf("%lld\n",cnt);
// for(int i=1;i<=n;i++){
// printf("%lld ",xv[i]);
// }
// cout<<"\n";
build(1,1,n);
char s;
for(int i=1;i<=m;i++){
cin>>s;
if(s=='E'){
x=read();
rt=x;
}else if(s=='V'){
x=read(),y=read();
changemin(1,in[x],y);
}else{
x=read();
if(x==rt){
printf("%lld\n",tr[1].minn);
}else if(in[x]<=in[rt]&&out[x]>=out[rt]){
int d=dep[rt]-dep[x]-1,y=rt;
for(int i=0;i<30;i++){
if(d&(1<<i)){
y=f[y][i];
}
}
printf("%lld\n",min(askmin(1,1,in[y]-1),askmin(1,out[y]+1,n)));
}else{
// printf("%lld %lld\n",in[x],out[x]);
printf("%lld\n",askmin(1,in[x],out[x]));
}
}
}
return Elaina;
}
/*
3 7
0 1
1 2
1 3
Q 1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1
5 11
0 1
1 2
1 3
2 4
2 5
Q 1
Q 2
Q 3
Q 4
Q 5
E 4
Q 1
Q 2
Q 3
Q 4
Q 5
*/
都看到这了,真的不点个赞吗(>ω<*)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本