【8.12测试】辉夜的二叉树
辉夜的二叉树
【题目背景】
又是某高中学生会无聊的一天。可爱的辉夜在繁忙的学习之余,仍抽空欣赏她 n 个节点的二叉树。
【问题描述】
突然,由于某种神秘力量,她的二叉树每个节点都带上了一个权值。她看到这个神奇的二叉树,想到了一条水题。由于真的太水了,她又魔改了一下。她看着你好奇的目光,偷偷告诉了你题目。
给出一棵 n 个节点,节点有权值的二叉树,第 i 个点的点权为 a[i]。有 3 种操作(修改或查询)
1. 修改点 x 的点权。
2. 对于点 x 的子树,交换每个节点的左右儿子。
3. 选择一个点 x ,从根开始往下走,假设当前走到点 y ,若 a[x]<= a[y],则向 y 的左儿子走,否则向 y 的右儿子走,问能否走到节点 x 。
然而辉夜大小姐想起了 自己的题被 暴力踩标程 的恐惧,给了非常友善的暴力分。
【输入格式】
第一行 2 个整数 n ,m ,表示二叉树的节点个数与操作数。
接下来 n行
第 i 行 3 个整数。a[i],lc ,rc ,分别表示点 i 的初始权值,左儿子的编号,右儿子的编号。
接下来 m行
每行第一个数 ops ,表示操作类型,如上所述。
若 ops=1 ,接下来两个整数 x 权值改为 y。
若 ops=2 ,接下来一个整数 x ,表示把点 x 的子树每个点的左右儿子交换
若 ops=3 ,接下来一个整数 x ,如上所述。
【输出格式】
对于每个 ops=3 的操作,输出 YES 或 NO 。
【样例输入】
3 7
10 2 3
5 0 0
5 0 0
3 1
3 2
3 3
1 3 100
3 3
2 1
3 3
【样例输出】
YES
YES
NO
YES
NO
【数据范围】
对于 10% 数据,n,m <=5000
另有 35% 数据,没有操作 2 。
对于 100% 数据,n,m <=100000
题解:暴力65分wdm!666(正解树链剖分)先献上暴力程序。
#include<iostream> #include<algorithm> #include<queue> #include<cmath> #include<cstring> #include<cstdlib> #include<cstdio> using namespace std; const int N=100002; int x,y,n,m,vc,s; int a[N],l[N],r[N],c[N]; bool op,fy[N]; bool dfs(int u){ if(u==x) return 1; if(l[u]==0 && r[u]==0) return 0; if(c[u]%2==0){ if(a[x]<=a[u]) dfs(l[u]); else dfs(r[u]); } else{ if(a[x]<=a[u]) dfs(r[u]); else dfs(l[u]); } } void SWAP(int u){ c[u]++; if(l[u]==0 && r[u]==0) return; SWAP(l[u]); SWAP(r[u]); } int main(){ freopen("kaguya.in","r",stdin); freopen("kaguya.out","w",stdout); scanf("%d %d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d %d %d",&a[i],&l[i],&r[i]); fy[l[i]]=1; fy[r[i]]=1; } for(int i=1;i<=n;i++) if(fy[i]==0) { s=i; break; } for(int i=1;i<=m;i++){ scanf("%d",&vc); if(vc==1){ scanf("%d %d",&x,&y); a[x]=y; } if(vc==2){ scanf("%d",&x); SWAP(x); } if(vc==3){ scanf("%d",&x); op=dfs(s); if(op==0) printf("NO\n"); else printf("YES\n"); } //cout<<i; } return 0; }