CodeForces 797D Broken BST

$dfs$,线段树。

通过观察可以发现,某位置要能被找到,和他到根这条路上的每个节点的权值存在密切的联系,且是父节点的做儿子还是有儿子也有联系。

可以从根开始$dfs$,边走边更新线段树,如果遍历左儿子,那么将$[1,val-1]$全部加$1$,否则将$[val+1,n]$全部加$1$,回溯的时候减$1$,判断某位置能否到达可以比较单点值与深度的关系。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <queue>
#include <stack>
#include <vector>
#include <algorithm>
using namespace std;

int f[400010];
int s[400010];
int res;

void pushDown(int rt)
{
	if(f[rt]==0) return ;
	s[2*rt] += f[rt];
	s[2*rt+1] += f[rt];
	f[2*rt] += f[rt];
	f[2*rt+1] += f[rt];
	f[rt] = 0;
	return ;
}

void pushUp(int rt)
{
	s[rt] = s[2*rt] + s[2*rt+1];
}

void update(int L,int R,int val,int l,int r,int rt)
{
	if(L<=l&&r<=R)
	{
		s[rt] += val;
		f[rt] += val;
		return ;
	}

	int m = (l+r)/2;
	pushDown(rt);
	if(L<=m) update(L,R,val,l,m,2*rt);
	if(R>m)  update(L,R,val,m+1,r,2*rt+1);
	pushUp(rt);
}

void query(int pos,int l,int r,int rt)
{
	if(l==r)
	{
		res = s[rt];
		return;
	}

	int m = (l+r)/2;
	pushDown(rt);
	if(pos<=m) query(pos,l,m,2*rt);
	else query(pos,m+1,r,2*rt+1);
	pushUp(rt);

}

int n;
struct X
{
	int val;
	int left,right;
}node[100010];
int root;
int b[100010],sz;
int ans;

int get(int x)
{
	int L = 0,R = sz-1;

	while(L<=R)
	{
		int mid = (L+R)/2;
		if(b[mid]>x) R = mid-1;
		else if(b[mid] == x) return mid+1;
		else L = mid+1;
	}
}

int u[100010];

void dfs(int x,int y)
{
	query(node[x].val,1,n,1);
	if(res != y) {}
	else u[node[x].val]=1;

	if(node[x].left!=-1)
	{
		if(node[x].val>1) update(1,node[x].val-1,1,1,n,1);
		dfs(node[x].left,y+1);
		if(node[x].val>1) update(1,node[x].val-1,-1,1,n,1);
	}

	if(node[x].right!=-1)
	{
		if(node[x].val<n) update(node[x].val+1,n,1,1,n,1);
		dfs(node[x].right,y+1);
		if(node[x].val<n) update(node[x].val+1,n,-1,1,n,1);
	}

}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d%d%d",&node[i].val,&node[i].left,&node[i].right);

	for(int i=1;i<=n;i++) b[sz++] = node[i].val;
	sort(b,b+sz);
	for(int i=1;i<=n;i++)
	{
		node[i].val = get(node[i].val);
		u[node[i].val]=1;
	}

	int sum=0;
	for(int i=1;i<=n;i++) sum=sum+1;

	for(int i=1;i<=n;i++)
	{
		if(node[i].left!=-1) f[node[i].left] = 1;
		if(node[i].right!=-1) f[node[i].right] = 1;
	}

	for(int i=1;i<=n;i++)
	{
		if(f[i]) continue;
		root = i; break;
	}

	memset(f,0,sizeof f);
	memset(u,0,sizeof u);
	dfs(root,0);
	for(int i=1;i<=n;i++) sum=sum-u[node[i].val];

	printf("%d\n",sum);

	return 0;
}
时间: 2024-10-11 17:02:55

CodeForces 797D Broken BST的相关文章

Broken BST CodeForces - 797D

Broken BST CodeForces - 797D 题意:给定一棵任意的树,对树上所有结点的权值运行给定的算法(二叉查找树的查找算法)(treenode指根结点),问对于多少个权值这个算法会返回false. 方法:如果要求对于值x运行算法能访问到结点k,根据给定算法还有树,可以推出对于每个结点k的x的范围(即最小值,最大值)(某结点p左子树的结点的x全部小于p的权值,右子树的结点的x全部大于p的权值)(由于全部权值均为整数,即使只知道小于和大于也可以推出最小值.最大值). 然而,对于某个结

AC日记——Broken BST codeforces 797d

D - Broken BST 思路: 二叉搜索树: 它时间很优是因为每次都能把区间缩减为原来的一半: 所以,我们每次都缩减权值区间. 然后判断dis[now]是否在区间中: 代码: #include <map> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> using namespace std; #define maxn 100005

CodeForces 722A Broken Clock (水题)

题意:给定一个时间,然后改最少的数字,使得它成为12进制或者24进制. 析:24进制主要判是不是大于23,如果是把第一位变成0,12进制判是不是大于12,如果是再看第二位是不是0,是0,第一位变成1,不是第一位变成0, 如果等于0,第一位变成1,至于分钟,只要判是不是大于59,是把第一位变成0. 代码如下: #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include &

Codeforces Round #353 (Div. 2) D. Tree Construction (BST询问父亲节点)

原题请戳这里 题意: 给出n个不同的数,按照给出的顺序构造二叉排序树BST,第1个数为根节点.输出2-n个 节点的父亲节点. 分析: 二叉排序树的平均复杂度是log2n,最坏情况下变成线性的,复杂度为n. 对n个节点的插入操作如果用结构体指针的写法最坏情况下为n2=1010,这样会超时. 开始没有注意这点,TLE.但是正好复习了BST的插入操作递归和非递归的写法. 易知,插入的数的父亲节点是已插入的比它大或者比它小的与其最接近的数之一. 这个题利用set保存输入的数,用两个map分别记录左右孩子

CodeForces 258D Little Elephant and Broken Sorting(期望)

CF258D Little Elephant and Broken Sorting 题意 题意翻译 有一个\(1\sim n\)的排列,会进行\(m\)次操作,操作为交换\(a,b\).每次操作都有\(50\%\)的概率进行. 求进行\(m\)次操作以后的期望逆序对个数. \(n,m\le 1000\) 输入输出格式 输入格式: The first line contains two integers \(n\) and \(m\) \((1\leq n,m\leq 1000,n>1)\) -

Educational Codeforces Round 75 (Rated for Div. 2) A. Broken Keyboard

链接: https://codeforces.com/contest/1251/problem/A 题意: Recently Polycarp noticed that some of the buttons of his keyboard are malfunctioning. For simplicity, we assume that Polycarp's keyboard contains 26 buttons (one for each letter of the Latin alph

Codeforces Round #392 (div.2) E:Broken Tree

orz一开始想不画图做这个题(然后脑袋就炸了,思维能力有待提高) 我的做法是动态规划+贪心+构造 首先把题目给的树变成一个可行的情况,同时weight最小 这个可以通过动态规划解决 dp[x]表示以x为结点的子树,它的最小weight是多少 接着我们就只需要考虑每条边增加多少就可以了,这里可以用贪心的做法 ddfs(int x, int fa, int v) 这里v是表示给x结点最大多少增量,然后慢慢加就可以,返回没用掉的增量 其实这个做法有点奇怪,应该有更简便的做法(我觉得可以直接贪心做) #

CodeForces - 258D Little Elephant and Broken Sorting

Discription The Little Elephant loves permutations of integers from 1 to n very much. But most of all he loves sorting them. To sort a permutation, the Little Elephant repeatedly swaps some elements. As a result, he must receive a permutation 1,?2,?3

Codeforces #505(div1+div2) D Recovering BST

题意:给你一个升序的数组,元素之间如果gcd不为1可以建边,让你判断是否可以建成一颗二叉搜索树. 解法:dp,首先建图,然后进行状态转移.因为如果点k左端与i相连,右端与k相连,则i和k可以相连,同时像左右两端拓展. 最后判断1和n是否相连即可. #include<cstdio> #include<algorithm> #include<cstring> #include<cmath> #include<vector> using namespa