/* 功能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;
}