摘要:
ZOJ_3511 一种可行的思路就是如果我们把切蛋糕的方案排个序,每次切下来一块就算一下这块的边长,而且这一块必须不会再被切到。 为了实现上面的思路,我们不妨把每次切的方案记作(x,y),且x<y,那么很显然有一种排序方式是一定符合要求的,即按y-x的值由小到大排序。 接下来的问题就是怎么算边长了。实际上可以发现边长的数量是等于点的数量,于是我们不妨用线段树记录一下x、y之间点的数量,每切一刀就相当于把x+1、y-1之间所有的点删掉了,这样我们只要查询x、y之间点的数量,就可以将其作为我们当前切下来的这块蛋糕边的数量。最后蛋糕还剩一块没有统计,再看一下最后还剩多少个点就行了。#inclu 阅读全文
摘要:
UESTC_1425 更多和区间合并相关的线段树问题可以参考胡浩的博客:http://www.notonlysuccess.com/index.php/segment-tree-complete/。 这个题和HDU_3308很像,只不过要多处理一下区间加和的操作,为了能够方便的修改、获取左区间的右端点和右区间左端点的大小关系,可以用两个标记lx[]、rx[]分别表示当前区间左端点以及右端点的值。#include<stdio.h>#include<string.h>#define MAXD 100010int N, Q, a[MAXD], lc[4 * MAXD], rc 阅读全文
摘要:
HDU_3340 这个题目要查询一个区间内的面积和,很容易联想到用线段树去做,但关键的问题在于由于有添加一个多边形的操作,那么我们如何下传标记去修改一个区间的面积和? 由于涉及到下传标记就涉及到标记叠加,因此我们要设法把面积的增量转化成用可以叠加的标记进行计算的形式。 在计算几何求面积的时候有一种方法是转换成梯形的有向面积累加计算,而梯形的面积主要取决于两个底和高的长度。对于这个题来讲,梯形高的长度就是x轴上区间的长度,这个很容易求得,而两个底的长度恰好就是我们想要的可以叠加的标记,因为(a+b)*h/2+(c+d)*h/2=((a+c)+(b+d))*h/2,而且根据两个底的长度就可以算.. 阅读全文
摘要:
HDU_3016 为了处理起来方便,我们可以先将plank对h排个序,最后补一个(0,100000)的value为0的plank。我们可以用f[i]表示跳到第i个plank时value和的最大值进行dp,每次在寻找可以由哪些plank落到第i个plank上时可以借助线段树。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 100010int N, M, f[MAXD], num[4 * MAXD], col[MAXD];struct Plank{ int h, x1, x2, 阅读全文
摘要:
HDU_3874 这个题目和HDU_3333几乎一模一样,具体的思路可以参考我的HDU_3333的题解:http://www.cnblogs.com/staginner/archive/2012/04/13/2445104.html。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 50010#define MAXQ 200010long long int sum[4 * MAXD];int N, Q, a[MAXD], tx[MAXD], X, r[MAXQ], where[ 阅读全文
摘要:
FZU_1656 这个题目和HDU_3333几乎一模一样,具体的思路可以参考我的HDU_3333的题解:http://www.cnblogs.com/staginner/archive/2012/04/13/2445104.html。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 100010#define MAXQ 1010int sum[4 * MAXD], N, Q, a[MAXD], tx[MAXD], X, where[MAXD], r[MAXQ];struct Q 阅读全文
摘要:
HDU_3333 一开始死活想不出来怎么做,后来看了别人的题解发现原来这个题目要离线去做。 暂且不说为啥要离线去做,先说说大概统计的思路是怎样的。 为了能够使区间和表示的就是最终的结果,那么同一个数必然只能在线段树中出现一次,于是我们建立线段树的时候可以改成将每个a[i]逐一插入进去,如果当前要插入的a[i]已经在线段树中存在,那么就先将其从线段树中删掉,再将其插入到线段树中i这个位置,这样我们就避免了线段树中整数的重复的问题。 假如我们现在刚插入完a[y],那么我们就只要计算出[x,y]这个区间的和就可以作为对于[x,y]这个询问的结果了。因此我们可以按y的顺序依次回答每个问题。这也就是.. 阅读全文
摘要:
HDU_4027 这个题目和HDU_3954有点像,由于开方这种运算我们没办法直接就将一段的和更新出来,但会发现即便是2^63能够被开方的次数也是很少的,因为一个数到1或者0之后我们就没必要再更新这个数了。所以,我们可以用num[]表示一个区间中不为0、1的整数的个数,如果我们要进行开方操作的区间内num[]的值不为0,我们就可以递归找到要更新的数并将其更新,同时更新路径上sum[]以及num[]的值。这样由于每个数被更新的次数不会超过10次,而每次找到一个需要更新的数的复杂度是O(logN),所以总共的更新操作的复杂度约是O(10*N*logN),是可以接受的。 此外,这个题目有个小tric 阅读全文
摘要:
HDU_3954 一开始始终在纠结要怎样维护max,因为不同等级的人每次加的经验是不一样的,这样如果只用一个max来维护最大值的话是很难办的。看了胡浩的出题报告之后恍然大悟,既然一个max来维护是很难办的,那不妨就将max变成K个,max[i]表示等级为i的人的经验的最大值,这样max[i]的增加就很好处理了。 至于如何处理一个人的升级问题,既然有了max[i],那么我们就知道每个等级上是否有人的经验达到了need[i+1],一旦有人达到就直接找到这个人,并将路径上的max[i]和max[i+1]的值更新一下即可。由于K比较小,每个人最多升级K次,而每次找一个人的复杂度是logN,所以升级操作 阅读全文
摘要:
URAL_1707 这个题目一开始感觉好麻烦的,不过多读了几遍之后终于把模型抽象出来了,如果把(si,ti)看成一个点的话,那么后面就是不断地在查询某个矩形范围内是否至少存在一个点,如果该范围内至少存在一个点那么xj就是1,否则xj就是0。 这让我联想到了POJ_2352数星星那个题,那个题是问一个点(x,y)的左边、下边以及左下方一共有多少个点(后面用sum(x,y)表示这个结果),而我们不难把Ural这个题目化归成那个题,如果矩形左下角是(x1,y1),右上角是(x2,y2)的话,那么最后结果就是sum(x2,y2)+sum(x1-1,y1-1)-sum(x1-1,y2)-sum(x2,y 阅读全文