Categories
不学无术

九度OJ 题目1012:畅通工程

题目描述:
    某省调查城镇交通状况,得到现有城镇道路统计表,表中列出了每条道路直接连通的城镇。省政府“畅通工程”的目标是使全省任何两个城镇间都可以实现交通(但不一定有直接的道路相连,只要互相间接通过道路可达即可)。问最少还需要建设多少条道路?
输入:
    测试输入包含若干测试用例。每个测试用例的第1行给出两个正整数,分别是城镇数目N ( < 1000 )和道路数目M;随后的M行对应M条道路,每行给出一对正整数,分别是该条道路直接连通的两个城镇的编号。为简单起见,城镇从1到N编号。
注意:两个城市之间可以有多条道路相通,也就是说
3 3
1 2
1 2
2 1
这种输入也是合法的
当N为0时,输入结束,该用例不被处理。
输出:
    对每个测试用例,在1行里输出最少还需要建设的道路数目。
样例输入:
4 2
1 3
4 3
3 3
1 2
1 3
2 3
5 2
1 2
3 5
999 0
0
样例输出:
1
2
998

==============================
这个题目,概念上就是求非连通图里面联通子图的数量…道路嘛就是再加几条边能把各个联通子图连起来~
做法的话,用并查集弄吧~
并查集最简单的玩法就是,弄一个亲爹数组,数组里面存指向自己亲爹的指针,没爹的就是根了…
统计有几个没爹的就是统计有多少联通子图
==============================

#include
using namespace std;
int findRoot(int *parentAry, int currIndex)
{
if(parentAry[currIndex] == -1)
return currIndex; //没爹了,currIndex就是爹
else
{
int rootIndex = findRoot(parentAry, parentAry[currIndex]);
//压缩路径
parentAry[currIndex] = rootIndex;
return rootIndex;
}
}
int main()
{
int N;
while(cin >> N && N!=0)
{
int M;
cin >> M;
int *parentAry = new int[N];
int i;
for(i=0; i> x >> y;
x--; y--;
int parentX = findRoot(parentAry, x);
int parentY = findRoot(parentAry, y);
if(parentX != parentY)
{
//不在一个集合中,合并!
parentAry[parentX] = parentY; //将X当前的根挂在Y的根上
}
}
int count = 0;
for(i=0; i

Categories
不学无术

九度OJ 题目1109:连通图

题目描述:
    给定一个无向图和其中的所有边,判断这个图是否所有顶点都是连通的。
输入:
    每组数据的第一行是两个整数 n 和 m(0<=n<=1000)。n 表示图的顶点数目,m 表示图中边的数目。如果 n 为 0 表示输入结束。随后有 m 行数据,每行有两个值 x 和 y(0<x, y <=n),表示顶点 x 和 y 相连,顶点的编号从 1 开始计算。输入不保证这些边是否重复。
输出:
    对于每组输入数据,如果所有顶点都是连通的,输出”YES”,否则输出”NO”。
样例输入:
4 3
1 2
2 3
3 2
3 2
1 2
2 3
0 0
样例输出:
NO
YES

====================================
这两天弄几道简单的做做…
这个是图联通的检测,可以用DFS或者BFS做,其实函数给个int返回值,返回这个节点标记了几个,这样后面main函数里面就不用再遍历一次visited数组了~
发现以前申请的空间都不delete的,现在感觉就像便便了没擦屁股一样…
调试出来第一遍发现怎么都不对,后来细看发现申请出来的二维数组没有初始化…噗
呐,如果是BFS的话,按照数据结构书上讲,用队列来搞,不用递归就行了。把本层访问到的节点塞到工作队列中就行..
====================================

#include
using namespace std;
void DFS( bool **connMatrix, bool *visited, int N, int c)
{
//connMatrix: 连通矩阵
//visited :是否访问
//N : 节点数
//c : 当前节点编号
visited[c] = true; //Mark current node as visited
int i;
for(i=0; i> N && N != 0)
{
cin >> M;
//Create matrix and visited
bool **connMat = new bool*[N];
bool *visited = new bool[N];
int i;
for(i=0; i> x >> y;
x--;
y--; //Subscript starts from 1 in the input
connMat[x][y] = true;
connMat[y][x] = true;
}
//Manipulate
DFS(connMat, visited, N, 0);
bool flag = true;
for(i=0; i

Categories
不学无术

九度OJ 题目1172:哈夫曼树

题目描述:
哈夫曼树,第一行输入一个数n,表示叶结点的个数。需要用这些叶结点生成哈夫曼树,根据哈夫曼树的概念,这些结点有权值,即weight,题目需要输出所有结点的值与权值的乘积之和。
输入:
输入有多组数据。
每组第一行输入一个数n,接着输入n个叶节点(叶节点权值不超过100,2<=n<=1000)。
输出:
输出权值。
样例输入:
5
1 2 2 5 9
样例输出:
37

=================================
吐槽:VC6里面智能提示好像到while语句之类的循环里面就会失效,然后就只能盲打..Orz…
=================================

#include
#include
#include
using namespace std;
struct Node
{
int val;
Node *parent;
Node()
{
parent = NULL;
}
int getHeight()
{
int h = 0;
Node *p = parent;
while(p != NULL)
{
h++;
p = p->parent;
}
return h;
}
};
bool compare(Node *x, Node *y)
{
return x->val > y->val;
}
int main()
{
int N;
while(cin >> N)
{
vector workingSet;
Node *nodes = new Node[N]; //Primitive Nodes
int i;
for(i=0; i> nodes[i].val;
workingSet.push_back(&nodes[i]);
}
///
while(workingSet.size() > 1)
{
sort(workingSet.begin(), workingSet.end(), compare);
Node *small1 = workingSet.back();
workingSet.pop_back();
Node *small2 = workingSet.back();
workingSet.pop_back();
//Combine
Node *combined = new Node;
combined->val = small1->val + small2->val;
small1->parent = combined;
small2->parent = combined;
workingSet.push_back(combined);
}
//output
int sum = 0;
for(i=0; i

Categories
不学无术

九度OJ 题目1190:大整数排序

题目描述:
对N个长度最长可达到1000的数进行排序。
输入:
输入第一行为一个整数N,(1<=N<=100)。
接下来的N行每行有一个数,数的长度范围为1<=len<=1000。
每个数都是一个正数,并且保证不包含前缀零。
输出:
可能有多组测试数据,对于每组数据,将给出的N个数从小到大进行排序,输出排序后的结果,每个数占一行。
样例输入:
3
11111111111111111111111111111
2222222222222222222222222222222222
33333333
样例输出:
33333333
11111111111111111111111111111
2222222222222222222222222222222222

==========================================

#include
#include
#include
using namespace std;
struct BigInt
{
char data[1001]; // 高位在前,低位在后
};
int compare(const void *pA, const void *pB)
{
BigInt *a = (BigInt *)pA;
BigInt *b = (BigInt *)pB;
int len_a = strlen(a->data);
int len_b = strlen(b->data);
if(len_a < len_b) return -1; else if(len_a > len_b)
return 1;
else
{
int i;
for(i = 0; idata[i] != b->data[i])
return a->data[i] - b->data[i];
}
}
return 0;
}
int main()
{
char input[1001];
int N;
while(cin >> N)
{
BigInt *bigInts = new BigInt[N];
int i;
for(i=0; i> input;
strcpy(bigInts[i].data, input);
}
qsort(bigInts, N, sizeof(BigInt), compare);
for(i=0; i

Categories
不学无术

某年研究生复试题之二

根据二叉树的先序和中序序列,设计算法重构出这棵二叉树。(40分)
已知一棵二叉树的先序遍历序列是ABECDFGHIJ,中序遍历序列是EBCDAFHIGJ,请设计一个算法,将这棵二叉树的结构重构出来,并且输出它的三种深度优先遍历的结果(即先序、中序和后序序列)。
====================================
都是挺基础的题目嘛~
先序遍历是NLR,中序遍历是LRN
所以给了一个先序序列,比如题目中那个,那第一个元素(A)肯定就是那个N啦
然后再中序序列中找到N,就能把中序序列劈成两段了,(LEFT)N(RIGHT)
然后就递归,弄到到底了为止,嘿嘿:)
不过自己实现起来还是挺蛋疼的,能力有限唉唉唉
输出只搞了个后序的,其他类似反正。
====================================

#include
#include
#include
#include
using namespace std;
struct Node
{
char value;
Node *pLeft;
Node *pRight;
Node()
{
pLeft = NULL;
pRight = NULL;
}
};
void splitLNR(queue input, queue &left, queue &right, char N)
{
bool flag = false;
while(!input.empty())
{
char currVal = input.front();
if(currVal == N)
{
flag = true;
input.pop();
continue;
}
if(!flag)
{
left.push(currVal);
}
else
{
right.push(currVal);
}
input.pop();
}
}
void splitNLR(queue input, queue &left, queue &right, int pos)
// RIght subseries starts at position = pos
{
int count = 0;
while(!input.empty())
{
char currVal = input.front();
if(count == 0)
{
input.pop();
count++;
continue;
}
else if(count < pos) { left.push(currVal); } else { right.push(currVal); } input.pop(); count++; } } void printLRN(Node *root) { if(root == NULL) return; printLRN(root->pLeft);
printLRN(root->pRight);
cout << root->value << " "; } void run( queue A, queue B, Node* root)
//A: 先序, B:中序
{
if(A.empty())
return;
char N = A.front();
root->value = N;
queue leftB, rightB, leftA, rightA;
splitLNR(B, leftB, rightB, N);
splitNLR(A, leftA, rightA, leftB.size() + 1);
if(leftB.empty() && rightB.empty())
{
//N is the only element
return;
}
if(!leftA.empty())
{
Node *newNode = new Node;
root->pLeft = newNode;
run(leftA, leftB, newNode);
}
if(!rightA.empty())
{
Node *newNode = new Node;
root->pRight = newNode;
run(rightA, rightB, newNode);
}
}
int main()
{
queue inputA, inputB;
char *cNLR = "ABECDFGHIJ";
char *cLNR = "EBCDAFHIGJ";
int i;
for(i=0; i

Categories
不学无术

某年研究生复试机试题

读入一批以负数为结束的正整数,数据为5,7,2,4,9,-1,建立一个带头结点的链表,链表的每个结点中包含有两个指针:一个用于链接输入的先后顺序,另一个用于链接输入整数从小到大的顺序。并分别按两个指针方向进行遍历输出。
====================
这个考的基础知识,一个是链表的东西,指针啊什么的
另外就是单向链表怎么排序
我能想到的方法嘛~其实排序这个东西,给定当前的数值value
如果存在x,使得 val <=x < MINVALUE,那么x就是当前节点的后继了
后面这个MINVALUE,就是选定了这个x之后,把MINVALUE设定为x,然后继续遍历输入次序,看看还有没有比x更适合的节点了
有点无限逼近的味道…要注意的是指针操作的时候别把自己跟自己来比,不然输入时如果有相同数就会玩完了~
时间复杂度是O(n^2),不过嘛…这个节骨眼能想出方法就行
 
吐槽一句,VC6真他妈的太难用了!!!
=====================

#include
using namespace std;
struct Node
{
int val;
Node *ptrOrder;
Node *ptrSort;
Node()
{
ptrOrder = NULL;
ptrSort = NULL;
val = -1;
}
};
int main()
{
//const int MAX_SIZE = 100;
//int inputArray[MAX_SIZE];
//Initialize link head
Node root;
int input;
int arySize = 0;
Node *currNode = &root;
//Node *prevNode = NULL;
while(cin >> input)
{
if(input < 0 || arySize >= MAX_SIZE)
break;
Node *newNode = new Node;
newNode->val = input;
currNode -> ptrOrder = newNode;
currNode = newNode;
}
//Sort
currNode = &root;
while(currNode != NULL)
{
Node *nextNode = root.ptrOrder;
int min_val_max = 65535;
int currValue = currNode->val;
while(nextNode != NULL)
{
if(nextNode == currNode)
{
nextNode = nextNode->ptrOrder;
continue;
}
int nextValue = nextNode->val;
if(nextValue >= currValue && nextValue < min_val_max) { min_val_max = nextValue; currNode->ptrSort = nextNode;
}
nextNode = nextNode->ptrOrder;
}
currNode = currNode->ptrOrder;
}
//Output
currNode = root.ptrOrder;
while(currNode != NULL)
{
cout << currNode->val << " "; currNode = currNode -> ptrOrder;
}
cout << endl; currNode = root.ptrSort; while(currNode != NULL) { cout << currNode->val << " "; currNode = currNode -> ptrSort;
}
cout << endl; //Clear memory if you have enough time :) cin.get(); return 0; }

Categories
不学无术

1030. Travel Plan (30)

时间限制:400ms
A traveler’s map gives the distances between cities along the highways, together with the cost of each highway. Now you are supposed to write a program to help a traveler to decide the shortest path between his/her starting city and the destination. If such a shortest path is not unique, you are supposed to output the one with the minimum cost, which is guaranteed to be unique.
Input Specification:
Each input file contains one test case. Each case starts with a line containing 4 positive integers N, M, S, and D, where N (<=500) is the number of cities (and hence the cities are numbered from 0 to N-1); M is the number of highways; S and D are the starting and the destination cities, respectively. Then M lines follow, each provides the information of a highway, in the format:
City1 City2 Distance Cost
where the numbers are all integers no more than 500, and are separated by a space.
Output Specification:
For each test case, print in one line the cities along the shortest path from the starting point to the destination, followed by the total distance and the total cost of the path. The numbers must be separated by a space and there must be no extra space at the end of output.
Sample Input

4 5 0 3
0 1 1 20
1 3 2 30
0 3 4 10
0 2 2 20
2 3 1 20

Sample Output

0 2 3 3 40

=================================================
这题目嘛是单元最短路径算法的变种,主要变了俩地方:
1.最短路径可能不止1条
2.最后找出最短路中权重cost最小的一个
我不知道我的解法中数据结构是否有冗余的,不过反正是通过了(可能内存多占点吧)
主要就是用Dijkstra算法,但是
1.更新距离组的时候,如果碰到跟当前最好距离一样的,也应该加上
2.多算一个的最佳权重组
,更新条件是:A)发现了更好的距离的时候,直接更新权重组,因为距离是首先要考虑的
B)发现了和现在相同的距离的时候,如果cost比较小,更新一下
这样等Dijkstra算法结束后,我们已经能得到最短距离且权重cost最小的路径了。以前还想着再根据最短距离的各种回溯遍历一下求最小耗费,今天一想其实根本不需要!
算法中还有点不确定的地方,见下面的注释。
====================================================

#include
#include
#include
#include
using namespace std;
struct Node
{
vector best_from;
int best_dist;
int best_cost;
int best_cost_from;
vector linkedNodes;
Node()
{
best_dist = 65535;
best_cost = 65535;
best_cost_from = -1;
}
};
int main()
{
int N, M, S, D;
scanf("%d %d %d %d", &N, &M, &S, &D);
int **distances = new int*[N];
int **costs = new int*[N];
Node *nodes = new Node[N];
set working;
for(int i=0; i::iterator it = ptrCurrNode->linkedNodes.begin();
for(; it!=ptrCurrNode->linkedNodes.end(); it++)
{
int linkedId = *it;
if( working.find(linkedId) == working.end())
{
//这个点已经是确定点了...
//是不是不再考虑?
}
Node *ptrLinkedNode = &nodes[linkedId];
int distViaMe = ptrCurrNode->best_dist + distances[last_found_best][linkedId];
int costViaMe = ptrCurrNode->best_cost + costs[last_found_best][linkedId];
if(distViaMe < ptrLinkedNode->best_dist)
{
ptrLinkedNode->best_dist = distViaMe;
ptrLinkedNode->best_from.clear();
ptrLinkedNode->best_from.push_back(last_found_best);
ptrLinkedNode->best_cost = costViaMe;
ptrLinkedNode->best_cost_from = last_found_best;
}
else if (distViaMe == ptrLinkedNode->best_dist)
{
ptrLinkedNode->best_from.push_back(last_found_best);
if(costViaMe < ptrLinkedNode->best_cost)
{
ptrLinkedNode->best_cost = costViaMe;
ptrLinkedNode->best_cost_from = last_found_best;
}
}
}
//更新完后找出不确定点中最小距离的,加入确定点中
int minDist = 65535;
set::iterator set_it = working.begin();
for(; set_it != working.end(); set_it++)
{
int id = *set_it;
if( nodes[id].best_dist < minDist) { minDist = nodes[id].best_dist; last_found_best = id; } } set_it = working.find(last_found_best); working.erase(set_it); } //第三步 stack route;
int currIndex = D;
while(currIndex != S)
{
route.push(currIndex);
currIndex = nodes[currIndex].best_cost_from;
}
printf("%d ", S);
while(!route.empty())
{
printf("%d ", route.top());
route.pop();
}
printf("%d %d", nodes[D].best_dist, nodes[D].best_cost);
return 0;
}

======================================================

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	710	18/18
1	答案正确	0	790	6/6
2	答案正确	0	2570	6/6
Categories
不学无术

1054. The Dominant Color (20)

时间限制:100ms
Behind the scenes in the computer’s memory, color is always talked about as a series of 24 bits of information for each pixel. In an image, the color with the largest proportional area is called the dominant color. A strictly dominant color takes more than half of the total area. Now given an image of resolution M by N (for example, 800×600), you are supposed to point out the strictly dominant color.
Input Specification:
Each input file contains one test case. For each case, the first line contains 2 positive numbers: M (<=800) and N (<=600) which are the resolutions of the image. Then N lines follow, each contains M digital colors in the range [0, 224). It is guaranteed that the strictly dominant color exists for each input image. All the numbers in a line are separated by a space.
Output Specification:
For each test case, simply print the dominant color in a line.
Sample Input:

5 3
0 0 255 16777215 24
24 24 0 0 24
24 0 24 24 24

Sample Output:

24

==============================
这题目就是个投票选班长的题目,上个学期数据库老师课上讲过(可惜了,数据库后来没考好),瞬间犹如醍醐灌顶~

醍醐灌顶,出于《敦煌变文集·维摩诘经讲经文》:“令问维摩,闻名之如露入心,共语似醍醐灌顶。”佛教指灌输智慧,使人彻底觉悟。比喻听了高明的意见使人受到很大启发。

最笨的办法是每个人画正字,浪费空间,最后还要统计票数
最终的目的是要选出票数最多的一个人,那么可以这样做:

初始化:
班长候选人:叉叉叉
当前差额票数:1
然后拿一张选票,票面上的名字是Name
if Name == 当前的候选人:
差额票数++
else:
差额票数--
if 差额票数==0:
候选人 = Name
差额票数 = 1

这样的话,省时间也省空间:)
原理其实想通了很简单,因为我们只选一个人啊,只算净胜票数就行
净胜票数为0了,那就要被赶下台了!
从测试点的结果来看,的确有个测试点数据量挺大的…估计之前说的笨办法就要超时了..
=================================

#include
int main()
{
int M, N;
scanf("%d %d", &M, &N);
int resolution = M * N;
int currBest = -1;
int currCount = 1;
for(int i=0; i

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	790	12/12
1	答案正确	0	790	2/2
2	答案正确	60	780	2/2
3	答案正确	0	790	2/2
4	答案正确	0	710	2/2
Categories
不学无术

1046. Shortest Distance (20)

时间限制:100ms
The task is really simple: given N exits on a highway which forms a simple cycle, you are supposed to tell the shortest distance between any pair of exits.
Input Specification:
Each input file contains one test case. For each case, the first line contains an integer N (in [3, 105]), followed by N integer distances D1 D2 … DN, where Di is the distance between the i-th and the (i+1)-st exits, and DN is between the N-th and the 1st exits. All the numbers in a line are separated by a space. The second line gives a positive integer M (<=104), with M lines follow, each contains a pair of exit numbers, provided that the exits are numbered from 1 to N. It is guaranteed that the total round trip distance is no more than 107.
Output Specification:
For each test case, print your results in M lines, each contains the shortest distance between the corresponding given pair of exits.
Sample Input:

5 1 2 4 14 9
3
1 3
2 5
4 1

Sample Output:

3
10
7

=============================================
此题原以为很简单,刚想疑问为啥PAT上正确率就0.2几….自己做了才发现原来会超时,因为数据量很大。
最初的想法超级简单,就是记录下每个顶点间的距离,等到有查询的时候再一个个计算~结果尼玛第三个测试点妥妥的超时了!
肯定是算法有问题,因为算法实在太简单了。
后来嘛,后来去网上一搜,搜了一半想到两个问题:
1.整个圆圈的总长度知道了,我算出一边,那么另一边的长度一减就出来了
2.从点x到点y(假设x小于y)的长度,不就是从 1到y的长度减去从1到x的长度(1点为第一个点)
而从1到i的长度,其实在读入数据的时候不就可以计算了!!!!!

dist_sum[i] = dist[i-1] + currDist;

之所以这两种做法时间上差别那么多,
因为幼稚的方法里面,每次计算时间复杂度是O(n),一共M次查询就是O(M*n)
现在每次查询时间复杂度是O(1),M次查询也就O(M)
题目给的规模,n=100000, M=10000
差距可想而知~
=================================

#include
int getShortestDist(const int* dists, int N, int from, int to, long totalDist)
{
int dist_L, dist_R;
if(from > to)
{
int temp = from;
from = to;
to = temp;
}
dist_L = dists[to-1] - dists[from-1];
dist_R = totalDist - dist_L;
return (dist_L

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	780	14/14
1	答案正确	0	790	3/3
2	答案正确	10	1000	3/3
Categories
不学无术

1043. Is It a Binary Search Tree (25)

时间限制:400ms
A Binary Search Tree (BST) is recursively defined as a binary tree which has the following properties:

  • The left subtree of a node contains only nodes with keys less than the node’s key.
  • The right subtree of a node contains only nodes with keys greater than or equal to the node’s key.
  • Both the left and right subtrees must also be binary search trees.

If we swap the left and right subtrees of every node, then the resulting tree is called the Mirror Image of a BST.
Now given a sequence of integer keys, you are supposed to tell if it is the preorder traversal sequence of a BST or the mirror image of a BST.
Input Specification:
Each input file contains one test case. For each case, the first line contains a positive integer N (<=1000). Then N integer keys are given in the next line. All the numbers in a line are separated by a space.
Output Specification:
For each test case, first print in a line “YES” if the sequence is the preorder traversal sequence of a BST or the mirror image of a BST, or “NO” if not. Then if the answer is “YES”, print in the next line the postorder traversal sequence of that tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line.
Sample Input 1:

7
8 6 5 7 10 8 11

Sample Output 1:

YES
5 7 6 8 11 10 8

Sample Input 2:

7
8 10 11 8 6 7 5

Sample Output 2:

YES
11 8 10 7 5 6 8

Sample Input 3:

7
8 6 8 5 10 9 11

Sample Output 3:

NO

===================================
二叉搜索树与“镜像”的二叉搜索树,其实对称的东西只是部分特殊化了一下,所以搞定非对称的就行。
想了半天怎么用堆栈什么的实现,其实把自己绕紧了无底洞,干脆自定义结构弄嘛!
基本思路如下(对BST来说的)

工作队列q = 输入值
结果队列result = []
初始化根节点root(value)
root.left_bound = [-INF, value]
root.right_bound = [value, INF]
currNode = root
while len(q)>0 and currNode!=None:
当前队首数值为n
if n能放在当前节点左侧:
新建节点newNode
newNode.left_bound = [ currNode.left_bound[0], n]
newNode.right_bound = [ n, currNode.left_bound[1]]
newNode.parent = currNode
q.pop()
elif 能放在右侧:
新建节点newNode
newNode.left_bound = [ currNode.right_bound[0], n]
newNode.right_bound = [ n, currNode.right_bound[1]]
newNode.parent = currNode
######
currNode.cannotPlaceLeft = true
######
q.pop()
else:
result.push(currNode.value)
######
currNode.cannotPlaceLeft = true
######
currNode = currNode.parent
一切处理完之后,
while currNode != None:
result.push(currNode.value)
currNode = currNoew.parent

里面#####中间的一个布尔变量是防止重复访问左侧值设定的,比如说如下情况
8
X 10
此时左边没有东西,但是已经访问过了,如果不设置一个布尔值判断的话,假设当前有那么一个值=6的元素
当前处理位置在10,发现6放不进去,然后移到8的位置
就会觉得8左边可以塞进去
但其实已经是非法操作了
=================================================================

#include
#include
using namespace std;
const int INFI = 65535;
struct Node
{
int value;
Node* left;
Node* right;
Node* parent;
int left_bound[2];
int right_bound[2];
bool left_tried; //已经尝试过左侧
void setLeftBound(int val0, int val1)
{
left_bound[0] = val0;
left_bound[1] = val1;
}
void setRightBound(int val0, int val1)
{
right_bound[0] = val0;
right_bound[1] = val1;
}
bool canPlaceLeft(int val)
{
if(left != NULL)
return false;
if(left_tried)
return false;
if(val >= left_bound[0] && val < left_bound[1]) return true; return false; } bool canPlaceRight(int val) { if(right != NULL) return false; if(val >= right_bound[0] && val < right_bound[1]) return true; return false; } Node() { left = NULL; right = NULL; parent = NULL; setLeftBound(-INFI, INFI); setRightBound(-INFI, INFI); left_tried = false; } }; queue tryBST(queue input)
{
queue result;
Node root;
root.value = input.front();
root.setLeftBound(-INFI, root.value);
root.setRightBound(root.value, INFI);
input.pop();
Node* currNode = &root;
while(!input.empty() && currNode!=NULL)
{
int currVal = input.front();
if(currNode->canPlaceLeft(currVal))
{
//可以放在左侧
Node *pNewNode = new Node;
pNewNode->setLeftBound(currNode->left_bound[0], currVal);
pNewNode->setRightBound(currVal, currNode->left_bound[1]);
pNewNode->parent = currNode;
pNewNode->value = currVal;
currNode->left = pNewNode;
currNode = pNewNode;
input.pop();
}
else if(currNode->canPlaceRight(currVal))
{
//可以放在右侧
Node *pNewNode = new Node;
pNewNode->setLeftBound(currNode->right_bound[0], currVal);
pNewNode->setRightBound(currVal, currNode->right_bound[1]);
pNewNode->parent = currNode;
pNewNode->value = currVal;
currNode->right = pNewNode;
currNode->left_tried = true;
currNode = pNewNode;
input.pop();
}
else
{
result.push(currNode->value);
currNode->left_tried = true;
currNode = currNode->parent;
}
}
while(currNode != NULL)
{
//一直递归到根部加入遍历结果
result.push(currNode->value);
currNode = currNode->parent;
}
return result;
}
queue tryBSTRev(queue input)
{
queue result;
Node root;
root.value = input.front();
root.setRightBound(-INFI, root.value);
root.setLeftBound(root.value, INFI);
input.pop();
Node* currNode = &root;
while(!input.empty() && currNode!=NULL)
{
int currVal = input.front();
if(currNode->canPlaceLeft(currVal))
{
//可以放在左侧
Node *pNewNode = new Node;
pNewNode->setRightBound(currNode->left_bound[0], currVal);
pNewNode->setLeftBound(currVal, currNode->left_bound[1]);
pNewNode->parent = currNode;
pNewNode->value = currVal;
currNode->left = pNewNode;
currNode = pNewNode;
input.pop();
}
else if(currNode->canPlaceRight(currVal))
{
//可以放在右侧
Node *pNewNode = new Node;
pNewNode->setRightBound(currNode->right_bound[0], currVal);
pNewNode->setLeftBound(currVal, currNode->right_bound[1]);
pNewNode->parent = currNode;
pNewNode->value = currVal;
currNode->right = pNewNode;
currNode->left_tried = true;
currNode = pNewNode;
input.pop();
}
else
{
result.push(currNode->value);
currNode->left_tried = true;
currNode = currNode->parent;
}
}
while(currNode != NULL)
{
//一直递归到根部加入遍历结果
result.push(currNode->value);
currNode = currNode->parent;
}
return result;
}
int main()
{
queue input;
int N;
scanf("%d", &N);
for(int i=0; i result1 = tryBST(input);
if(result1.size() == input.size())
{
printf("YESn");
while(!result1.empty())
{
printf("%d", result1.front());
if(result1.size() != 1)
printf(" ");
result1.pop();
}
return 0;
}
result1 = tryBSTRev(input);
if(result1.size() == input.size())
{
printf("YESn");
while(!result1.empty())
{
printf("%d", result1.front());
if(result1.size() != 1)
printf(" ");
result1.pop();
}
return 0;
}
printf("NO");
//
return 0;
}

测试点	结果	用时(ms)	内存(kB)	得分/满分
0	答案正确	0	710	6/6
1	答案正确	0	790	6/6
2	答案正确	0	710	2/2
3	答案正确	0	720	3/3
4	答案正确	0	790	3/3
5	答案正确	0	700	2/2
6	答案正确	0	790	2/2
7	答案正确	0	790	1/1