Segment tree

Problem E: BST

Time Limit: 1 Sec   Memory Limit: 128 MB
Submit: 51   Solved: 12
[ Submit][ Status][ Web Board]

Description

A binary search tree is a tree in which every node has at most two children nodes (a left and a right 
child). Each node has an integer written inside it. If the number X is written inside a node, then the 
numbers in its left subtree are less than X and the numbers in its right subtree are greater than X. 
You will be given a sequence of integers between 1 and N (inclusive) such that each number appears in 
the sequence exactly once. You are to create a binary search tree from the sequence, putting the first 
number in the root node and inserting every other number in order. In other words, run insert(X, root) 
for every other number: 
insert( number X, node N ) 
  increase the counter C by 1 
  if X is less than the number in node N 
    if N has no left child 
      create a new node with the number X and set it to be the left child of node N 
    else 
      insert(X, left child of node N) 
  else (X is greater than the number in node N) 
    if N has no right child 
      create a new node with the number X and set it to be the right child of node N 
    else 
      insert(X, right child of node N) 
Write a program that calculates the value of the counter C after every number is inserted. The counter 
is initially 0.

Input

The first line contains the integer N (1 ≤ N ≤ 300 000), the length of the sequence. 
The  remaining  N  lines  contain  the  numbers  in  the  sequence,  integers  in  the  interval  [1,  N].  The 
numbers will be distinct.

Output

Output N integers each on its own line, the values of the counter C after each number is inserted into 
the tree.

In test cases worth 50% of points, N will be at most 1000.

Sample Input

41234532415835168724

Sample Output

01360124601247111315
#include<stdio.h>
#include<string.h>
#define LL(x) (x<<1)
#define RR(x) ((x<<1)|1)

int n;
const int maxn=300005;
struct Seg{
	int max;
	int min;
	int l,r;
}tree[maxn*4];

int dp[maxn+100];
int T[maxn+100];
long long sum;

void build(int l,int r,int k)
{
	tree[k].l=l;
	tree[k].r=r;
	tree[k].max=0;
	tree[k].min=n+1;
	if(l==r) return ;
	int mid=(l+r)>>1;
	build(l,mid,LL(k));
	build(mid+1,r,RR(k));
}

int Max(int a,int b){
	if(a<b) return b;
	return a;
}

int Min(int a,int b){
	if(a<b) return a;
	return b;
}

void update(int l,int r,int k,int v)
{
	if(l==r)
	{
		tree[k].max=tree[k].min=v;
		return ;
	}
	int mid=(tree[k].l+tree[k].r)>>1;

	if(v<=mid) update(l,mid,LL(k),v);
	else update(mid+1,r,RR(k),v);

	tree[k].max=Max(tree[LL(k)].max,tree[RR(k)].max);
	tree[k].min=Min(tree[LL(k)].min,tree[RR(k)].min);
}

int query_max(int l,int r,int k)
{
	if(l>r) return 0;
	if(l<=tree[k].l && tree[k].r<=r)
		return tree[k].max;
	int mid=(tree[k].l+tree[k].r)>>1;
	if(r<=mid) return query_max(l,r,LL(k));
	else if(l>mid) return query_max(l,r,RR(k));
	else
	{
		return Max(query_max(l,mid,LL(k)),query_max(mid+1,r,RR(k)));
	}
}

int query_min(int l,int r,int k)
{
	if(l>r) return 0;
	if(l<=tree[k].l && tree[k].r<=r)
		return tree[k].min;
	int mid=(tree[k].l+tree[k].r)>>1;
	if(r<=mid) return query_min(l,r,LL(k));
	else if(l>mid) return query_min(l,r,RR(k));
	else
	{
		return Min(query_min(l,mid,LL(k)),query_min(mid+1,r,RR(k)));
	}
}


int main()
{
	int i,j;
	int a,t1,t2;
	while(scanf("%d",&n)!=EOF)
	{
		memset(dp,-1,sizeof(dp));
		memset(T,0,sizeof(T));
		T[0]=T[n+1]=-1;
		build(1,n,1);
		sum=0;
		for(i=1;i<=n;i++)
		{
			scanf("%d",&a);
			t1=t2=-1;
			if(a==1)
			{
				t1=query_min(2,n,1);
				dp[a]=dp[t1]+1;
			}
			else if(a==n)
			{
				t1=query_max(1,n-1,1);
				dp[a]=dp[t1]+1;
			}
			else
			{
				t1=query_max(1,a-1,1);
				t2=query_min(a+1,n,1);
				if(T[t1]>T[t2])
					dp[a]=dp[t1]+1;
				else
					dp[a]=dp[t2]+1;
			}
			update(1,n,1,a);//puts("fff");
			
			sum+=dp[a];
			T[a]=i;
			printf("%lld\n",sum);
		}
	}
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值