BOJ 1257 Jim 和 Tradia的故事II-第K小数---初学线段树

/* 功能Function Description:     BOJ 1257 Jim 和 Tradia的故事II-第K小数---初学线段树
   开发环境Environment:          DEV C++ 4.9.9.1
   技术特点Technique:
   版本Version:
   作者Author:                   可笑痴狂
   日期Date:                 	 20120807
   备注Notes:
   Description
		Tradia对数据结构很感兴趣,她懂得很多有用的数据结构,比如链表、二叉树、图等等。最近她在学习堆的有关知识,并对堆能够在log2N的时间复杂度内返回当前集合的最值感到十分的满意。可是我们都知道,Tradia是一个求知欲很强的学生,她并不满足于得到集合的最值(最大、最小值),同时她还想获得集合当前的第K小数,并且要求每次查询的复杂度要与log2N相当,如果复杂度比log2N还低的话,她或许会以此来申请明年的图灵奖。
		然而Tradia自己能力有限,没能想出什么好的解决办法,这时她想到了Jim,希望他能帮帮忙。但是Jim现在正忙着给大家出题呢,所以这个光荣的任务只能拜托聪明的你了!



	Input
		输入包含多组测试数据。
		首先第一行输入一个数T(T<=10),表示总共有T组测试数据。
		接下来是每组测试数据,第一行是一个数N(N<=50000),表示有N个操作。接着是这N个操作的描述,操作只有两种:
		1、ADD X,表示往当前集合添加一个正数X(X<=200000)
		2、QUERY K,查询当前集合的第K小数
		注意,一开始集合都是空的,输入保证集合中每个数都不相等,且QUERY操作都是合法的。


	Output
		首先,输出Case #X:其中X代表是第X组数据(具体格式参照样例)。
		然后对每组数据的QUERY查询,输出当前第K小的数即可。


	Sample Input

		2
		2
		ADD 1
		QUERY 1
		4
		ADD 2
		QUERY 1
		ADD 1
		QUERY 1


	Sample Output

		Case #1:
		1
		Case #2:
		2
		1



*/
//自己的代码---未提交验证--没找到题目来源
#include<stdio.h>
#include<stdlib.h>

typedef struct node
{
	int num;
	node *lc,*rc;
	int num_of_lc;
}node;

void insert(int t,node *&T)
{
	if(T==NULL)
	{
		T=(node *)malloc(sizeof(node));
		T->num=t;
		T->lc=T->rc=NULL;
		T->num_of_lc=1;
		return;
	}
	else
	{
		if(t>T->num)
			insert(t,T->rc);
		else
		{
			++T->num_of_lc;
			insert(t,T->lc);
		}
	}

}

void query(int k,node *&T)  //查询第k小数
{
	if(k==T->num_of_lc)
		printf("%d\n",T->num);
	else if(k<T->num_of_lc)
		query(k,T->lc);
	else
		query(k-(T->num_of_lc),T->rc);
}

int main()
{
	int m,i,n,t;
	char cmd[10];
	node *T;
	scanf("%d",&m);
	for(i=1;i<=m;++i)
	{
		T=NULL;
		printf("Case #%d:\n",i);
		scanf("%d",&n);
		while(n--)
		{
			scanf("%s%d",cmd,&t);
			if(cmd[0]=='A')
				insert(t,T);
			else
				query(t,T);
		}
	}
	return 0;
}

//网上代码一:(动态创建)
#include <stdio.h>
#include <stdlib.h>

typedef struct node 
{
     int data;
     struct node *lc,*rc;
     int num_of_lc;
}*nodeptr;
nodeptr Tree;

void insert(int m,nodeptr &T)//插入
{
     if(T==NULL)
     {
         T=(nodeptr)malloc(sizeof(node));
         T->data=m;
         T->lc=NULL;
         T->rc=NULL;
         T->num_of_lc=0;
     }
     else 
     {
        
         if(m>T->data)
             insert(m,T->rc);
         else 
         {  
             T->num_of_lc++;
             insert(m,T->lc);
           
         }
     }
    

}
void query(int m,nodeptr &T)//查找k小数
{
     if(m==T->num_of_lc+1)
     {
         printf("%d\n",T->data);
     }
     else if(m<T->num_of_lc+1)
     {
         query(m,T->lc);
     }
     else if(m>T->num_of_lc+1)
     {
         query((m - T->num_of_lc-1),T->rc);
     }

}
int main(void)
{
     int t;
     int n;
     char opt[60];
     int m=0;
     char num[8];

     scanf("%d",&t);

     for(int i=0;i<t;i++)
     {
         Tree=(nodeptr)malloc(sizeof(node));
         Tree=NULL;

         printf("Case #%d:\n",i+1);
         scanf("%d\n",&n);
         for(int j=0;j<n;j++)
         {
             gets(opt);            //他这里读取的有点麻烦,可以改成上边的
             switch(opt[0])
             {
             case 'A':    
                 m=0;
                 while(opt[4+m])
                 {
                     num[m]=opt[4+m];
                     m++;
                 }
                 num[m]='\0';
                 m=atoi(num);	 //将字符串转化为int型数值
                
                 insert(m,Tree);
                 break;
             case 'Q':
                 m=0;
                 while(opt[6+m])
                 {
                     num[m]=opt[6+m];
                     m++;
                 }
                 num[m]='\0';
                 m=atoi(num);
                 query(m,Tree);
                 break;
             }
         }

     }

     // system("pause");
     return 0;
}
 
//网上代码二:(静态创建)
#include <iostream> 
#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 

using namespace std; 

#define MAXN 200000 

struct node 
{ 
	int l,r; 
	int c; 
}Tree[2 * MAXN + 1];   //个人感觉不用乘2

void build(int a,int b,int k) 
{ 
	if (a == b) 
	{ 
		Tree[k].l = a; 
		Tree[k].r = b; 
		Tree[k].c = 0; 
		return; 
	} 
	int mid = (a + b) >> 1; 
	Tree[k].l = a; 
	Tree[k].r = b; 
	Tree[k].c = 0; 
	build(a,mid,k * 2); 
	build(mid + 1,b,k * 2 + 1); 
	return; 
} 

void insert(int b,int k) 
{ 
	if (Tree[k].l == Tree[k].r && b == Tree[k].l) 
	{ 
		Tree[k].c += 1; 
		return; 
	}
	int mid = (Tree[k].l + Tree[k].r) >> 1; 
	if (b <= mid) 
		insert(b,k * 2); 
	else 
		insert(b,k * 2 + 1); 
	Tree[k].c = Tree[k * 2].c + Tree[k * 2 + 1].c; 
	return; 
} 

void search(int b,int k,int &cnt) 
{ 
	if (Tree[k].l == Tree[k].r) 
	{ 
		cnt = Tree[k].l; 
		return; 
	} 
	int mid = (Tree[k].l + Tree[k].r) / 2; 
	if (b > Tree[k * 2].c) 
		search(b - Tree[k * 2].c,k * 2 + 1,cnt); 
	else 
		search(b,k * 2,cnt); 
} 

int main() 
{ 
	int n,cas; 
	scanf("%d",&cas); 
	for (int j = 1; j <= cas; ++j) 
	{ 
		printf("Case #%d:\n",j); 
		scanf("%d",&n); 
		build(1,MAXN,1); 
		int i; 
		char op[10]; 
		int b; 
		for (i = 0; i < n; ++i) 
		{ 
			scanf ("%s %d",op,&b); 
			if (strcmp(op,"ADD") == 0) 
			{ 
				insert(b,1); 
			} 
			else 
			{ 
				int cnt; 
				search(b,1,cnt); 
				printf("%d\n",cnt); 
			} 
		} 
	}
	return 0;
} 


 

你可能感兴趣的:(线段树)