Unix网络编程.第五,六章笔记.

# Unix世界里经常看到的 pst  是 pseudo terminal 的意思啊。

# ps -t pts/6 -o pid,ppid,tty,stat,args,wchan

ps 命令的进程状态。 S表示进程在睡眠,I表示进程在等待输入,O表示进程在等待输出。当进程在S状态时,wlan指示了更详细的状态信息。

# SIGSTOP 和 SIGKILL 两个posix信号不可以被caught.

# 缺省情况下,Unix的信号是不排在队列中的。这意味着多个相同signal到达的时候如果没有来得及处理,就只会记下一个signal.如果需要稳定的信号支持,就要使用RealTime Posix接口。

# init 进程的PID是 1.

# 可以用sigprocmask函数block和unblock信号。This let us protect a critical region of code by preventing certain signals from being caught while that region of code is executing.

# 对于 Unix System V 和 Unix98, the child of a process does not become a zombie if the process sets the disposition of SIGCHLD to SIG_IGN. unfortunately, tis works only under System V & Unix98. Posix明确指票这个行为是未定义的。The portable way to handle zombies is to catch SIGCHILD & call wait or waitpid.

# waitpid 有个 WNOHANG 选项可以让waitpid立即返回。

# POSIX定义了asynchronous I/O model .但是 few systems support POSIX asynchronous I/O. The main difference between asynchronous I/O model and signal-driven I/O model is that with signal-driven I/O, the kernel tells us when an I/O operation can be initiated but with asynchronous I/O, the kernel tells us when an I/O operation is completed.

# 想得到本机到某台机的RTT。怎么做呢?kao,不要太容易啊。用 ping 啊!!!

使用Necessitas在Android平台上运行Qt程序失败

什么是 Necessitas?

NecessitasQtAndroid操作系统上的一个移植,同时提供了Qt CreatorAndroid的集成。Necessitas计划为你提供了Android平台下的Qt,以及一个一流的平易近人的IDE,方便你在安卓平台下管理,开发,部署,运行 调试你的Qt应用。

什么是Minstro?

Necessitas也是Ministro的官网。MinistroLGPL Qt共享库提供了一个系统范围的下载器(downloader)和安装器(installer)。你可以在Andorid软体市场获得Ministro

如何安装Necessitas SDK开发包?

相当地easy啊!http://sourceforge.net/projects/necessitas/files/ 下载sdk开发包。有linux, win, mac 三个平台下的。安装过程傻瓜式 next next next 。哥尝试在Linux下安装出错了。安装程序没有加载起来。

zausiu@potassium:/tmp$ ./necessitas-0.3-online-sdk-installer-linux 

./necessitas-0.3-online-sdk-installer-linux: error while loading shared libraries: libgobject-2.0.so.0: cannot open shared object file: No such file or directory

 

我先尝试在deibian安装linux版本。结果安装文件启动时加载libglobject.so失败了!但是明明在/lib目录下啊!解决不了,唔知点解!就只好在win7下安装了windows版本。注意要勾选上装 ant,如果你的系统里之前没有安装ant的话。装好ant后还要把ant的路径添加入环境变量里。

如何安装Android SDK开发包?

去官网下载了然后安装。简单地令人发指!!!哥不能讲怎么安装它,免得说我侮辱你的智慧。

http://developer.android.com/sdk/index.html

开始开发

运行在安卓上的Qt程序被编译成共享对象(shared objects)。一个Java Launcher,已经集成在necessitas sdk里,会加载这个shared objects。当然,对于应用开发者,这个Java Launcher是完全透明的。要注意的是,Qt包含了很多互相引用的库,只有Android V1.6以上才支持这个functionality

 

哈。最最重要的。尝试第一个将被部署到android上的Qt应用。用安装好的 Necessitas Qt Creator创建了一个GUI程序。运行。。。运行。报错了!!!哭啊。

ma-make: *** [install_target] Error 2

The process "D:\necessitas\QtCreator\bin\ma-make.exe" exited with code 2.

Error while building project 4android (target: Android)

When executing build step 'Copy application data'

"When executing build step 'Copy application data'"google了一下。木有得到有价值的信息。不知道如何解决啊。哈~~那就不管了!!!

copyright ykyi.net

 

 

linux的soname,链接库的问题.

第一次看到soname是读<程序员的自我修养.第一册:链接库>看来的。顺便说一下,这本书确实是本好书吖,国内出的难得技术好书。后来在公司的项目中把它从windows平台下移植到linux下,写makefile时用到过。

 

再后来又忘记了。今天再次看到soname的时候就有点记不起来了。又只好搜索了一些资料看。趁热打铁把学会的东西记下来。

linux为尝试解决动态链接库版本冲突的问题(windows平台下称之为DLL HELL),引入了soname进制。linux的动态链接库的扩展名约定为.so 即shared object的缩写。下面的makefile语句来自于哥今年上半年写的makefile文件:

VERSION_NUM := 1.0.0
soname = lib(dirname).so.(firstword (subst ., ,(VERSION_NUM)))
LINKFLAGS := -shared -Wl,-soname,$(soname) -L. -lpthread -lrt -lpentagon -lcross_platform
其中的变量$(soname)会被替换为eibcomm.so.1。再看看LINKFLAGS变量指定的几个选项. -shared 表示要生成一个shared object,即动态共享库. -pthread -lrt -lpentagon -lcross_platform 是要链接其它几个库,thread和linux的posix线程库,rt是一个和实时系统相关的库它提供了高精度的时间函数。

比较奇怪的是 -Wl,-soname,$(soname) 它们之前用逗号分开,而不是用空格分开。实际上这几个东东会被gcc传给ld(linux下的链接器)作为链接器的参数。gcc规定的写法就是这样的。指定的soname会被链接器写入到最终生成的elf文件中(linux下的可执行文件格式)。要查看elf文件的段布局什么的,可以用readelf工具。

 

最终生成的文件将命名为 libname.so.x.y.z 的形式。soname是libname.so.x的格式(也不尽然,这只是一个convetion,并非在语法或机制上强行要求)。接着把生成的so文件拷贝到/usr/lib 或者 /lib,这两个文件夹是系统用来放置动态链接库的地方。debian下没有把/usr/local/lib作为默认的动态链接库文件夹.可以通过改/etc/ld.so.conf 文件把更多的路径加入。再运行 ldconfig,更新cache中的库文件信息。为什么要用cache呢,有人就问了!因为library实在太多了咯,cache就被引用了。cache是个好东西啊!!!

这个时候依赖 libname.so.x 的文件就可以找到这个library并加载起来了。但是编译程序时还是找不到呢.编译程序时通常会写 -lname 这个时候会先找 libname.so 再找 libname.a 文件,结果找不到。link就会抱怨没有找到这个库文件。为了让编译通过,于是你就用 ln -sf libname.so libname.so.x.y.z (这个是realname,版本号部分可能只有x.y两个部分) 建一个软链接!搞定!

copyright ykyi.net

关于听陈光荣教授《混沌的故事》讲座的心得报告

    在听你陈老师(陈光荣教授,见文章未尾的介绍)的报告之前没有听说过“混沌数学”的概念。阅读了网络上的一些资料以后,有了大致的认识。早在初中生的年代,有在数学科普杂志上看到过“模糊数学”的概念。我想,混沌数学应该就是模糊数学近乎罢。

陈老师的讲座重点在浅显介绍混沌数学,并没有涉及太多混沌理论的学术内容。报告从牛顿时期的三大定律讲起,当时的的科学界普高认为世界是一个确定的机械系统。到科学家彭家莱在研究天体运动的三体问题时提出了定性分析的研究方向,这是混沌的启蒙思想。陈老师讲三维空间有四种状态:发散,收敛,周期振荡,第四种即“混沌”。数学家Stephen Smale提出了“马蹄理论”又是“混沌数学”领域的一重要理论。我粗略地把“马蹄理论”理解成一个马蹄形状被压缩,拉伸,对折变换,不断重复这一过程,就变成了“chaos”。华人数学家李天岩发表了论文“Period Three Implies Chaos”标志着“离散混沌数学理论的诞生”。这个理论被称为“李.约克理论”。它的核心部分是“区间中存在不可数个初始点,函数从这些点出发的迭代点序列既不是周期的,又不趋向于任何周期轨道。序列的这种特殊状态是混沌的(chaotic)”。“混沌理论”这个概念在大陆由北京大学的朱照宣教授引入。

陈老师在讲混沌理论的历史发展的故事中穿插了小故事给听众解释混沌理论。陈老师举了一个足球场的例子。一个四周用铁丝网封闭的足球场,一群小孩子在足球场内踢足球。这个足球飞向什么位置是不可预测的。这就近似一个“混沌系统”。我自己的理解,在每一个时间点如果可以知道小孩踢球的位置和力量大小以及风速等等物理量,就可以预测出皮球的运动方向啊。唔,我想得岂不是跟拉普拉斯的理论一样了啊机械决定论!!!要被自然辩证法老法鄙视的啊!为了不违反自然辩证法的原则。你要想修补我的想法。这应该是一个视角的问题。如果能得到各种影响物理量的精确值固然可以测出皮球的运动方向,但对于一个非常复杂的系统,要得到所以物理量的精确值是不可能的,于是“混沌”就同来了。混沌,真是好高深的理论啊!!!

陈老师在结束部分讲了“混沌理论”在天体物理学中的应用。Princeton University 的 Peter Goldreich 认为认为太阳系行星的共振是混沌的;混沌决定了太阳系行星的形成,导致地球上的某些“生物种类灭绝” 甚至某些天体的“物质消亡” ,让天体的“牛顿时钟” 最终趋于混沌。幻灯片播放的太阳系(Solar System)的图片相当地漂亮啊。最新的混沌理论认为太阳系起始于混沌状态,在两亿年内又将进入混沌。由微小的扰动会引发巨大无比的突变,行星的轨道最终都趋向于混沌。天体物理学是相当的难懂,看着这些美丽神秘的宇宙深处的图片,我觉得我所具备的物理知识不足以理解宇宙中的神秘星体。从哲学的大尺度高度,任务事情都是出生,发展,高潮,最终走向毁灭。大规模有序的运动里会在局部,某些子过程中蕴含无序的过程。看似无序的过程也必有运动的规律。Actually,我不能理解,Chaotic Solar System是个什么样的system

http://ykyi.net zausiu’s blog

提问阶段,有人问到了计算机的问题,陈老师总结为计算机不可能产生理论上真正随机的数据。这跟我的知识是一致的,计算机只能产生伪随机数。与是又想到之前看Linux内核的书,Linux内核里有一个什么什么池的东东,这个东东用来搜集所有随机发生的事件:如电流噪声,键盘中断等等用它来贡献随机数。咦,这不就能产生真正随机的数字了吗?马上又想到,这是一个看问题的尺度的问题。把时间尺度放小到内核能收集到的两次随机事件之间,这个间隔内产生的随机数依然是通过公式计算到的可预测的数字。果然还是伪随机数。又想到之间的PPT中有讲陈老师用电路可以产生真正的“混沌信号”。那么把这路电路引入到计算机体系中,不就可以产生真正的随机数了吗?唔!那就不对了呀。那只可能是:“混沌”和“随机”并不是完全相等的概念。

讲座结束后。我跟同学讨论了未来“生物计算机”的猜想。应用哲学思想的否定之否定规律。信号从过去的“模拟信号”发展到现在占统治地位的“离散信号”,必定在以后又会发展到更高层次的“模拟信号”,近似生物电神经系统的通讯发式,将完全超越现在的二进制的冯诺依曼体系的计算机。生物电的模拟信号能携带更丰富的信息,并且能够描述真正“混沌”的“模糊”状态。而现在的二进制计算机只能用精确的离散数字近似描述模糊的东西。这样的计算机有什么现实意义呢!至少就能产生真正的随机数了。肯定有意义非凡的现实意义啊。科学学术是先不负责现实意义的,那是工程师们的任务。

/////////////////

讲座题目:混沌的故事

 

演讲人:陈关荣教授,香港城市大学

 

演讲时间:125日上午 10:00-11:30

 

演讲地点:中山大学东校区信息学院楼  207

 

演讲摘要:许多人都听说过,南美洲的一只蝴蝶轻轻地扇动一下翅膀可能会在美国德克萨斯州引发一场龙卷风。这一通俗解释作为“混沌”的代名词经历了人们认识和建立科学意义上的混沌理论的漫长历程,理解到“蝴蝶效应”是混沌的一个基本特征。本讲座以故事的形式向理工科师生介绍混沌的基本概念和混沌理论的发展历史。报告力求通俗生动而不失严谨清晰。内容并不要求听众具有混沌知识,因而也欢迎其他有兴趣的非理工科师生参加。

 

演讲人简介

 

陈关荣教授1981年获中山大学计算数学硕士学位,是中大校友。他于1987年获美国Texas A&M 大学应用数学博士学位,其后在莱斯大学和休斯顿大学任教。自2000年起,他接受香港城市大学讲座教授职位工作至今,在该校成立了“混沌与复杂网络”学术研究中心并担任中心主任。他长期从事非线性科学研究,自1981年以来,发表了多篇SCI杂志论文和出版了多部研究专著,他引次数达一万六千多次,SCI h指数为 62,被ISI评定为工程学高引用率研究人员。

 

陈关荣教授现任IEEE《电路与系统》杂志(IEEE Circuits and Systems Magazine)主编和国际《分岔与混沌》杂志(International Journal of Bifurcation and Chaos)主编,曾经担任过许多国际学术会议主席和组织者、曾任IEEE电路与系统学会非线性电路与系统技术委员会主席。他是IEEE Fellow(自1996年),曾获4 SCI最佳杂志论文奖,2008年获国家自然科学二等奖(第一完成人),2010年获何梁何利科学与技术进步奖,2011年获俄罗斯圣彼得堡国立大学授予荣誉博士学位和俄罗斯欧拉基金会颁发欧拉金质奖章。他是中山大学等国内外多所大学的荣誉或客座教授,并曾多次应邀到过30多个国家讲学。

sicily 1022 Poor contestant Prob 解题报告。

 

         解  题  报  告
 
1 1022 Poor contestant Prob原题中文大意;
 
对于大约十万条数据:如果共奇数条数据则找到最中间那条记录。如果有偶数条记录则忽略。
 
2 算法思想及解题用到的主要数据结构;
 
因为数据的规模比较大。如果给十万条记录排序的话显然会超时。考虑到题目只需要找到最中间那条。易想到把数据平分成两部分,第一部分的数据全部大于第二部分的数据。创建两个堆结构。第一部分的较大数据建大小顶堆,第二部分的较小数据建成大顶堆。在插入数据的过程中,动态维护这两个堆,使小顶堆的元素数等于大顶堆的元素数或者小顶堆的元素比大顶堆的元素多一。本题用性线表来存储堆。
 
3 详细解题思路;
 
因为最终需要输出一个字符串。为了节省拷贝字符串的开销,把字符串存到一个字符串池中,而每个堆中的元素只维护这个字符串池的索引号。
 
初始时,小顶堆和大顶堆的大小都是0。
 
1. 当输入第一条数据时,把这条数据放入小顶堆中。
 
2. 当输入更多数据时:
 
2.1 如果小顶堆和大顶堆的元素个数一样多。为保证添加新数据后,我们需要的最中间的数据在小顶堆的上部。又分两种情况处理:
 
2.1.1 如果待加入数据大于或等于大顶堆的堆顶元素。则把这个待加入数据加入小顶堆。调整小顶堆.
 
2.1.2 如果待加入数据小于大顶堆的堆顶元素.则把大顶堆的堆顶元素弹出添加到小顶堆,调整这两个堆。之后,把待加入数据加入大顶堆。
 
2.2 如果小顶堆和大顶堆的元素个数不一样多。因为前面的约定,那么必定是小顶堆的元素个数比大顶堆的元素个数多一个。仍然分两种情况:
 
2.2.1 如果待加入数据大于小顶堆的堆顶元素。则把待加入数据加入小顶堆并调整,调整后把小顶堆的堆顶弹出加入大顶堆并调整。小顶堆在弹出堆顶元素后再调整一次。
 
2.2.1 如果待加入数据不大于小顶堆的堆顶元素。则把该数据加入大顶堆,调整大顶堆。
 
输入结束时直接取小顶堆的堆顶元素即要求的解。根据元素中的字符串索引可以拿到需要打印的字符串,本题中即那位poor contestant。
 
4 逐步求精算法描述(含过程及变量说明);
int g_name_pool_index = 0;   // 名字池的当前索引号.

char g_name_pool[100001][11];  // 用来存名字的字符串池.



下面是堆相关的描述。

struct heap_elem_t

{

// string _name;

int _name_index;  // 名字的索引

int _solved_count;  // 原题意中表示解决了多少个问题.用这个数量比较堆元素的大小。

};

// STL 用的堆算法的比较算子.

struct heap_elem_less_comparator

{

bool operator()(const heap_elem_t& left,  const heap_elem_t& right)

{

return left._solved_count < right._solved_count;

}

};



// STL 用的堆算法的比较算子.

struct heap_elem_larger_comparator

{

bool operator()(const heap_elem_t& left,  const heap_elem_t& right)

{

return left._solved_count > right._solved_count;

}

};

heap_elem_less_comparator less_comp;

heap_elem_larger_comparator larger_comp;

// 从下往而上调整堆。用到了STL的堆调整算法。堆元素存在线性表中,但不用第一个元素。因为之前的版本用自己写的堆调整算法为了计算坐标方便就不用第一个元素。

inline void adjust_heap_up(heap_elem_t heap[], int tail_pos, bool inc)

{

if ( inc )

{

push_heap(heap+1, heap+tail_pos+1, larger_comp);

}

else

{

push_heap(heap+1, heap+tail_pos+1, less_comp);

}

}

// 把堆顶元素弹出.并调整余下的元素仍然是一个堆。也用了STL的算法.

inline void popup_the_top(heap_elem_t heap[], int tail_pos, bool inc)

{

if ( inc )

{

pop_heap(heap+1, heap+tail_pos+1, larger_comp);

}

else

{

pop_heap(heap+1, heap+tail_pos+1, less_comp);

}

}

// 下面是自已写的堆调整算法。有从上而下的调整,也有从下而上的调整。

/** 调整堆.从下往下调整.

* @param heap 堆的首地址.用顺序表存放堆.但不用下标为0的元素.这个元素可用来作临时存储.

* @param summit_pos 堆顶的位置.summit_pos > 0

* @param tail_pos 最后一个元素的位置.tail_pos > 0

* @param inc 是否建小顶堆.如果false则大顶堆.

*/

void adjust_heap_top2bottom(heap_elem_t heap[], int summit_pos, int tail_pos, bool inc)

{

int i;

heap[0] = heap[summit_pos];  // 存下堆顶的元素先.

for ( i = 2 * summit_pos; i <= tail_pos; i *= 2 )

{

if ( inc )  // 调整小顶堆

{

if ( i < tail_pos && heap[i]._solved_count > heap[i+1]._solved_count )

i++;

if ( ! (heap[0]._solved_count > heap[i]._solved_count) )

break;

}

else  // 调整大顶堆

{

if ( i < tail_pos && heap[i]._solved_count < heap[i+1]._solved_count )

i++;

if ( ! (heap[0]._solved_count < heap[i]._solved_count) )

break;

}

heap[summit_pos] = heap[i];

summit_pos = i;

}

heap[summit_pos] = heap[0];

}



/** 调整堆.从下往上调整.

* @param heap 堆的首地址.用顺序表存放堆.但不用下标为0的元素.这个元素可用来作临时存储.

* @param tail_pos 最后一个元素的位置.tail_pos > 0

* @param inc 是否建小顶堆.如果false则大顶堆.

*/

void adjust_heap_bottom2top(heap_elem_t heap[], int tail_pos, bool inc)

{

int i;

heap[0] = heap[tail_pos];

for ( i = tail_pos; i > 1; i /= 2 )

{

int parent_pos = i / 2;

if ( inc )  // 调整小顶堆

{

if ( heap[parent_pos]._solved_count > heap[0]._solved_count )

{

heap[i] = heap[parent_pos];

}

else

{

break;

}

}

else  // 调整大顶堆

{

if ( heap[parent_pos]._solved_count < heap[0]._solved_count )

{

heap[i] = heap[parent_pos];

}

else

{

break;

}

}

}



heap[i] = heap[0];

}

5 程序注释清单(重要过程的说明);

// poor_guy.cpp : Defines the entry point for the console application.
//

#include <algorithm>
#include <string>
#include <vector>
#include <string.h>
#include <stdio.h>

using namespace std;

template<typename T> class my_vector
{
public:
my_vector(T* addr)
{
m_ary = addr;
m_ava_idx = 0;
}
~my_vector()
{
//  delete []m_ary;
}

T& operator[](int index)
{
return m_ary[index];
}

void push_back(const T& v)
{
m_ary[m_ava_idx++] = v;
}

void resize(int size)
{
m_ava_idx = size;
}

void shrink(int dec)
{
m_ava_idx -= dec;
}

int size()
{
return m_ava_idx;
}
private:
T*   m_ary;
int  m_ava_idx;
};

// 堆的结点定义
int g_name_pool_index = 0;
char g_name_pool[100001][11];

struct heap_elem_t
{
// string _name;
int _name_index;
int _solved_count;
};

heap_elem_t g_heap_elems0[50002];
heap_elem_t g_heap_elems1[50002];

struct heap_elem_less_comparator
{
bool operator()(const heap_elem_t& left,  const heap_elem_t& right)
{
return left._solved_count < right._solved_count;
}
};

struct heap_elem_larger_comparator
{
bool operator()(const heap_elem_t& left,  const heap_elem_t& right)
{
return left._solved_count > right._solved_count;
}
};

heap_elem_less_comparator less_comp;
heap_elem_larger_comparator larger_comp;

/************************************************************************/
/* inc 为真时调整为小顶堆,为false时调整为大顶堆。                      */
/************************************************************************/
inline void adjust_heap_up(heap_elem_t heap[], int tail_pos, bool inc)
{
if ( inc )
{
push_heap(heap+1, heap+tail_pos+1, larger_comp);
}
else
{
push_heap(heap+1, heap+tail_pos+1, less_comp);
}
}

inline void popup_the_top(heap_elem_t heap[], int tail_pos, bool inc)
{
if ( inc )
{
pop_heap(heap+1, heap+tail_pos+1, larger_comp);
}
else
{
pop_heap(heap+1, heap+tail_pos+1, less_comp);
}
}

int main(int argc, char* argv[])
{
const int BUFF_LEN = 64;
char buff[BUFF_LEN];
int case_count;  // 记有多少个case;
int contestant_count;
my_vector<heap_elem_t> littletop_heap(g_heap_elems0);
my_vector<heap_elem_t> bigtop_heap(g_heap_elems1);
heap_elem_t contestant;
string name;
// vector<string> output_vec;

scanf("%d", &case_count);
for ( int i = 0; i < case_count; i++ )
{
littletop_heap.resize(1);  // 为了方便计算.下标0的位置不存堆的元素.
bigtop_heap.resize(1);
g_name_pool_index = 0;
contestant_count = 0;

while(true)
{
scanf("%s", buff);

int little_heap_count = littletop_heap.size() - 1;
int big_heap_count = bigtop_heap.size() - 1;

if ( buff[0] == 'Q' )  // 查询. Querry
{
if ( little_heap_count == big_heap_count || 0 == contestant_count )
{
printf("No one!\n");
//output_vec.push_back("No one!\n");
}
else
{
printf("%s\n", g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back(g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back("\n");
}
}
else if ( buff[0] == 'E' )  // 结束.
{
if ( little_heap_count == big_heap_count || 0 == contestant_count )
{
printf("Happy BG meeting!!\n");
//output_vec.push_back("Happy BG meeting!!\n");
}
else
{
printf("%s%s",g_name_pool[littletop_heap[1]._name_index], " is so poor.\n");
//output_vec.push_back(g_name_pool[littletop_heap[1]._name_index]);
//output_vec.push_back(" is so poor.\n");
}

break;
}
else if( buff[0] == 'A' )// 加入参赛者数据.
{
contestant_count ++;

scanf("%s", g_name_pool[g_name_pool_index]);
contestant._name_index = g_name_pool_index;
g_name_pool_index++;
scanf("%d", &contestant._solved_count);

if ( 1 == contestant_count )  // 第一个参赛者数据.
{
littletop_heap.push_back(contestant);
}
else if ( little_heap_count == big_heap_count )  // 两个堆的元素相等.
{
// 新元素大于大顶堆的堆顶元素,所以插入小顶堆.
if ( contestant._solved_count >= bigtop_heap[1]._solved_count )
{
littletop_heap.push_back(contestant);
adjust_heap_up(&littletop_heap[0], littletop_heap.size()-1, true);
}
else
{
heap_elem_t top = bigtop_heap[1];
popup_the_top(&bigtop_heap[0], bigtop_heap.size()-1, false);
bigtop_heap.shrink(1);

bigtop_heap.push_back(contestant);
adjust_heap_up(&bigtop_heap[0], bigtop_heap.size()-1, false);

littletop_heap.push_back(top);
adjust_heap_up(&littletop_heap[0], littletop_heap.size()-1, true);
}
}
else  // 不等.只可能是小顶堆比大顶堆多1.
{
if ( contestant._solved_count > littletop_heap[1]._solved_count )
{
littletop_heap.push_back(contestant);
adjust_heap_up(&littletop_heap[0], littletop_heap.size()-1, true);

heap_elem_t top = littletop_heap[1];
popup_the_top(&littletop_heap[0], littletop_heap.size()-1, true);
littletop_heap.shrink(1);

bigtop_heap.push_back(top);
adjust_heap_up(&bigtop_heap[0], bigtop_heap.size()-1, false);
}
else
{
bigtop_heap.push_back(contestant);
adjust_heap_up(&bigtop_heap[0], bigtop_heap.size()-1, false);
}
}
}
}

if ( i + 1 < case_count )
{
printf("\n");
//output_vec.push_back("\n");
}
}

//for ( int i = 0; i < output_vec.size(); i++ )
//{
// cout << output_vec[i];
//}

return 0;
}

 

 
//////// 上面的代码在中山大学ACM网站 www.soj.me 上通过.目前的成绩是第14名.
 
Rank  14    2011-12-07 10:00:19    0.18 sec    2160 KB    6971 Bytes     C++   zausiu
 
注意上面的代码绝不能用C++的标准IO cin cout 做输入输出.如果用C++的IO流会造成超时。我为了调这个超时问题调了整整一天!死活想不到是因为C++ IO的问题.童鞋,一定要用 scanf 和 printf 啊。面对十万级的IO,尤其是在做ACM题,cin cout 是魔鬼。
 
原因是:
 
More should be noted about I/O operations in C++. Due to their complex underlying implementation  models, cin and cout are comparatively slower than scanf and printf. The difference in performance is shown by many experiences to be more significant if the program is compiled by G++. Therefore if a problem has huge input, using cin and cout will possibly lead to Time Limit Exceed.
 
6 测试数据;
 
用一个简单的BASH脚本来创建测试用例。
 
#! /bin/bash

INDEX=1

SHRESHOLD=100000   // 建十万条数据.



while [ INDEX -ltSHRESHOLD ]

do

echo "ADD nameINDEXRANDOM"

let "INDEX=$INDEX+1"

done

 

 
 
7 对时间复杂度,空间复杂度方面的分析.
 
时间复杂度是O(log n), 空间复杂度是 O(n).
 
 
 
附原题:
 
 
 
 
 
1022. Poor contestant Prob
 
Description
 
 
 
As everybody known, “BG meeting” is very very popular in the ACM training team of ZSU.
After each online contest, they will go out for “smoking”. Who will be the poor ones that have to BG the others? Of course, the half who solve less problems.
The rule runs well when the number of the contestants is even. But if the number is odd, it is impossible to divide them into two equal parts. It gives a dilemma to the BG meeting committee. After a careful discussion with Mr. Guo, a new rule emerged: if the number of the contestant is odd, the committee will first sort the contestants according to the number of problems they solved, and then they will pick out the middle one. This poor boy or girl will have no chance to attend the BG meeting.
Strange rule, isn`t it?
As the number of the contestants is becoming more and more large, the committee need to write a program which will pick out the poor one efficiently.
Note that: Every contestant solves different number of problems. The total number of the contestants will not exceed 10^5.
 
 
 
Input
 
 
 
There are several cases in the input. The first line of the input will be an integer M, the number of the cases.
Each case is consisted of a list of commands. There are 3 types of commands.
1. Add xxx n : add a record to the data base, where xxx is the name of the contestant, which is only consisted of at most 10 letters or digits, n is the number of problems he/she solved. (Each name will appear in Add commands only once).
2.Query :
3.End :End of the case.
 
 
 
Output
 
 
 
1.For the Query command: If the current number of contestants is odd, the program should output the poor contestant’s name currently even if there is only one contestants, otherwise, just out put “No one!” (without quotes).
2.For the End command:
If the total number of contestants in the data base is even, you should out put “Happy BG meeting!!”(without quotes),otherwise, you should out put the “xxx is so poor. ”(without quotes) where xxx is the name of the poor one.
3.Each case should be separated by a blank line.
 
 
 
Sample Input
 
2
Add Magicpig 100
Add Radium 600
Add Kingfkong 300
Add Dynamic 700
Query
Add Axing 400
Query
Add Inkfish 1000
Add Carp 800
End
 
Add Radium 100
Add Magicpig 200
End
Sample Output
 
No one!
Axing
Radium is so poor.
 
Happy BG meeting!!
Problem Source
 
ZSUACM Team Member