作者归档:Eurce

[POJ 3368]

Frequent values

说好的RMQ问题,结果又用线段树A了…

题意是:一个长度为n(1<=n<=100000)的非递减序列,共q(1<=1<=100000)次询问,求下标(l,h)范围内出现最频繁的元素的次数。 一开始照着RMQ问题想,还看了个ST算法(O(NlgN)预处理,O(1)在线查询),结果也没想明白怎么用。 又回头想了下,发现线段树是可以用的。由于序列非递减,连续的相同元素压缩成一个点作为线段树叶结点,记录元素在原数组中的下标范围;树分叉结点则保存子树下最频繁次数值,插入时则是按照压缩后的点编号进行处理,由此建树O(NlgN),每次查询是O(lgN)。

[POJ 1151]

Atlantis

本来是属于线段树的,但数据范围太小,硬是用暴力A掉了 -____-##

相比之前的好题……本题简直可以用“丑陋”来形容……比起线段树的运用和构思算法本身,更麻烦的反而是坐标离散化,而且由于POJ本身的问题,G++对double处理有缺陷(后来发现是输入用%lf输出用%f),转用C++后,对STL的编译又和G++的不一样……结果就是写好程序后各种卡编译错误……

[POJ 2352]

Stars

继续线段树+树状数组练手题。

这题先对某坐标轴方向排序后,便能将二维降为一维处理了。没太大难度。

线段树:

树状数组:

[POJ 1195]

Mobile phones

二维树状数组。

推出一维的后便很易想出二维解法了,单次更新/查询的时间复杂度升为O(lgN*lgN),因此还是可以接受的。

久违的1A。。。

[POJ 3321]

Apple Tree

树状数组例题。

“用DFS求出树结点对应的区间范围”比较难想……后面的区间值修改和查询都比较简单了。分别用了线段树和树状数组进行了求解。

线段树:

树状数组:

[POJ 2104]

K-th Number

划分树。

题意是,给一个长度为n的数组,之后有m次询问,每次询问为三元组(l,r,k),问数组中第l到第r个元素间第k小的元素是什么。

又是一题很有意思的题目,常规解法的时间复杂度在这里是完全不可行的,必须预先建树后才能O(lgN)地回答每次询问。但看了划分树的建树思想后还是推了很久。

划分树是基于线段树的,其基本思想在于父节点上[L,R]区间上[l,r]中的第k小元素,如何O(1)时间地递推到左子树或右子树中,这样总共O(lgN)次后便能得到答案。

[POJ 2482]

Stars in Your Window

这题前面竟然是一封情信,字里行间都饱含作者的深情……于是又搜了下kinfkong,是位中大的前辈哦,都31岁结婚了。他博客里的文章也挺有意思的……

扯远了,回到题目本身吧。题面是:在二维平面上有N颗星星,各有一个亮度值c,问如果用一个长W宽H的矩形来括住某些星星,如何使窗口内星星亮度和最大。

说实在的,题目本身也出得非常巧妙。解题需要两次利用区间值求和的思想,即在[a,b]区间上加c,相当于在顺序遍历的基础上在a点加c,b+1点减c。第一次是在y轴方向上,若在(x,y)点处有一颗星星亮度为c,则在(x,y+H)上增加一颗亮度为-c的星星。这样,由y=0向上更新线段亮度值,便能将矩形区域求最大和转换成线段求最大和。第二次则是在x轴方向上的,对横坐标x亮度为c的星星,增加一颗x+W处亮度为-c的星星,这样便能进一步将线段最大和转换成点最大值。由此,便能利用线段树在每次插入星星的同时O(lgN)地更新最大亮度值了。

不过题目分类里写得这题属于“静态二叉检索树”。。。。这个暂时还没想出来该怎么写。。。

[POJ 2750]

Potted Flower

分类表里最后一道线段树了。

题意大概是:有一个环,环上有N个整数,求在每次更新环上某个值后,环(除整个环外)任意弧上最大的整数和。

乍看下去,虽然提示是用线段树,但还是想了很久也没思路。再看了下输入规模,N最大10^5,更新次数M也是10^5,于是单次更新的处理时间只能是O(lgN)的。这样便能看出来是每次更新都在线段树上作O(lgN)深度的线段信息更新,再由根结点信息得到结果。

这里由左右子结点得到父结点信息的题推关系还是挺麻烦的……要考虑左连续区间最值和对应的最右元素位置,右连续区间最值和对应的最左元素位置,以及区间中任意子连续区间上的最值,再加上区间上全部整数和,总共是6个量。

这里要记录左右最值区间对应边界位置是因为,最后在根结点处计算时是可以将最右和最左看作连续的(环的性质),这样如果子结点上左右区间有重叠时,直接相加便会出错了,因此记录边界便能在仅当左右区间不重叠时才计算值。

另外这题要求不能取整个环上所有元素,因此实际上求的是最小弧,再用全部整数和减去最小值便能得到最大弧了。

[POJ 3678]

Katu Puzzle

很神奇的2-SAT问题。找了一篇赵爽的《2-SAT解法浅析》。作者是高中生啊,查了下却发现是05年交大ACM总冠军队的成员……Orz

题目抽象出来后就不难做了,建一个含2*N个点的有向图,边由逻辑运算给出,边(u,v)表示选了u点则必须选v。编号为i的点对应图中i*2和i*2+1的两个点,分别表示i点取值为1、0。点A、B间由逻辑运算生成的边如下:

A & B == 1: 增加边(A*2+1,A*2)和(B*2+1,B*2);

A & B == 0: 增加边(A*2,B*2+1)和(B*2,A*2+1);

A | B == 1: 增加边(B*2+1,A*2)和(A*2+1,B*2);

A | B == 0: 增加边(A*2,A*2+1)和(B*2,B*2+1);

A ^ B == 1: 增加边(A*2,B*2+1)、(B*2+1,A*2)、(A*2+1,B*2)和(B*2,A*2+1);

A ^ B == 0: 增加边(A*2,B*2)、(B*2,A*2)、(A*2+1,B*2+1)和(B*2+1,A*2+1);

建好图后求强连通分量。最后判断是否对所有的i=0:N-1,是否有i*2和i*2+1不在同一强连通分量中,若成立则原问题有解,否则无解。

这里被 A & B == 1 和 A | B == 0 卡了一下……不可取的点直接引入必败边的做法非常巧妙……

同样分别使用了两次DFS和tarjan来求强连通分量,代码分别如下:

[codeforces] 杀入Div. 1!

各种磕绊过后……终于我也Candidate Master啦!附送链接:eurce01

从#184开始……一场没算分,一场C题sort用了greater_equal导致TLE,一场电脑被A没做之后……终于我也Rating 1742啦!!

其实Div. 2的题还是挺轻松的……各种水题虐虐也能加分,不过也是#189开始才过了D题,结果直接Rank 17了。

但貌似这种难度的题才相当于Div. 1的B题啊……目测接下来还是狂跪的节奏……

无论如何还是bless自己一下吧……