上一页 1 ··· 63 64 65 66 67 68 69 70 71 ··· 85 下一页
  2011年11月2日
摘要: HDU_2242 这个题目首先可以求出边双连通分量并进行缩点,如果边双连通分量的个数只有一个的话就必然无解,之后我们把缩好的点建成一个新图,这个图实际上就是一棵树。 如果我们随便找个点当做树根,并把图画成树形结构的话,就会发现实际上我们只要求出除树根外每个节点以及其下方的所有节点的权值和即可,每求出一个权值和,就算一下人数差并更新一下min。同时,为了充分利用子问题的解,我们在计算结果的时候可以采用dfs的方式,每个节点返回自己以及自己下方的所有节点的权值和。 需要说明的是,由于这个题目存在两点之间有多条边的情况,于是在用tarjan时就要判断一下当前扫描的边是否是之前来到这个节点的边的... 阅读全文
posted @ 2011-11-02 02:29 Staginner 阅读(858) 评论(0) 推荐(0) 编辑
  2011年11月1日
摘要: POJ_2352 由于我们在读入数据的时候已知了前面星星的个数,实际上再减去当前星星右边的星星的数量即可,因此我们可以用一个线段树存储横坐标区间里的星星个数,每读入一个星星就修改并查询一次,并记录level即可。#include<stdio.h>#include<string.h>#define MAXD 32010#define MAXN 15010int M, N, tree[4 * MAXD], num[MAXN];void init(){ for(M = 1; M < 32003; M <<= 1); memset(tree, 0, sizeo 阅读全文
posted @ 2011-11-01 18:58 Staginner 阅读(237) 评论(0) 推荐(0) 编辑
摘要: POJ_3468(1) 在消化了PPT上思想之后,又重新做了一下这个题目。 不妨将原数组的元素记作a[i],然后我们用堆建立两棵线段树,一棵的原数组为x[i](x[i]=a[i]-a[i-1],即原数组的差分数组),另一棵的原数组为ix[i](ix[i] = i*x[i])。 为什么要这么做呢?原因如下。 如果我们记S[i]为x[i]的前缀和,我们会发现S[i]实际上就是a[i],也就是说差分的前缀和就等于原数组中的对应元素(因而才说差分是前缀和的逆运算)。我们不妨设SS[i]为S[i]的前缀和,在求区间和时用SS[b]–SS[a-1]自然是很方便的,然而对于修改操作,无论是维护S[i... 阅读全文
posted @ 2011-11-01 15:57 Staginner 阅读(212) 评论(0) 推荐(0) 编辑
摘要: POJ_3468 现在用的方法还是比较慢的,因为YTQ给我那个PPT还没深入研究透,PPT上面对这种的题的解法是用维护前缀和的前缀和以及{n*An}的前缀和来实现的,而我用的方法就是比较朴素的做lazy标记,来标识该区间内每个元素增加了多少。如果需要查询子区间时,再更新子区间的和,并将lazy标记传递下去。#include<stdio.h>#include<string.h>#define MAXD 100010int N, M, Q;long long int tree[4 * MAXD], lazy[4 * MAXD], res;int left[4 * MAXD] 阅读全文
posted @ 2011-11-01 01:09 Staginner 阅读(282) 评论(2) 推荐(0) 编辑
摘要: UVA_12299 首先分析简单的情况,数字代表最大堆,2必胜,3必输,4必胜,……其实偶数必胜是显然的,但奇数就不好说了,于是我们换个角度考虑。 如果说3必输的话,那么最后能把最大堆是3的情况留给Bob那么自己必然会赢,而能确保最大堆是3的情况就只有4、5、6了,而对于7,无论自己如何设置,都会把4、5、6其中的一个留给Bob,故自己必输。 同理,7必输的话,把7留给Bob就必胜,于是…… 这样推完,其实Bob能赢的情况就是在n=2^k-1(k = 2, 3, 4,…)的时候,其他时候Alice都是必胜的。#include<stdio.h>int main(){ int n; . 阅读全文
posted @ 2011-11-01 00:14 Staginner 阅读(440) 评论(0) 推荐(0) 编辑
  2011年10月31日
摘要: UVA_12299 这个是湖南省赛的题目,要是早点能学到YTQ后来给我PPT的话,当时也许就过掉了。 这个题目比一般的RMQ多了一个shift操作,用堆存储线段树然后直接自底向上更新一下即可。#include<stdio.h>#include<string.h>#include<ctype.h>#define MAXD 100010#define INF 1000000000int N, M, Q, tree[4 * MAXD];char b[50];int a[50], d[50], n;int Min(int &x, int &y){ r 阅读全文
posted @ 2011-10-31 23:21 Staginner 阅读(528) 评论(0) 推荐(0) 编辑
摘要: POJ_2777 这个题目在用线段树自顶向下处理的时候,需要对每个节点做两个标记,一个是当前区间包含的颜色,另一个就是lazy标记。 lazy标记是为了节省更新子节点颜色的时间,也就是在染色时没有必要立刻更新子节点的颜色,而是在自顶向下查询时如果发现需要更新子节点,那么再将lazy标记不断下传并更新子节点,这样就节省了时间。 对于颜色的表示,由于染色种类较少,因此可以用二进制数来表示每个区间的染色情况。#include<stdio.h>#include<string.h>#define MAXD 100010int L, T, O, M, res, tree[4 * M 阅读全文
posted @ 2011-10-31 19:32 Staginner 阅读(213) 评论(0) 推荐(0) 编辑
  2011年10月29日
摘要: POJ_1753 时隔多日,已经是第3次写这个题目了,在熟悉了位运算之后使得更有效率地解决了这个问题。 同时,这个题目在枚举上也有一点小的技巧。如果要是暴力枚举的话,一旦棋盘到了16*16的话显然就吃不消了(一个东欧区域赛的题目),实际上我们完全可以只枚举第一行的操作,之后,如果我们想把棋子全部翻成一种颜色的话,那么第二行的操作就是固定的了(因为第一行的棋子的状态对第二行棋子的翻转进行了约束,如果想把第一行的棋子变成白色,那么第二行中位于第一行黑色棋子下方的位置必须翻转,反之亦然),那么第三行、第四行的操作显然也是固定的了。 这样即使是16*16的棋盘也只有15*16*2^16的复杂度,... 阅读全文
posted @ 2011-10-29 19:44 Staginner 阅读(990) 评论(1) 推荐(1) 编辑
  2011年10月27日
摘要: POJ_2828 这个题目和POJ_2182很像,我们可以从后往前依次查询,排在p的右边就说明自己是排在第p+1位的,因此,我们可以维护一个线段树,节点值表示当前区间内还有多少个位置,寻找到当前第p+1个位置的所在地时,就把value存进去,然后把这个位置删除,即自底向上更新一遍节点值即可。#include<stdio.h>#include<string.h>#define MAXD 200010int tree[4 * MAXD], q[MAXD], a[MAXD], b[MAXD], N, M;void init(){ int i, j; for(M = 1; M 阅读全文
posted @ 2011-10-27 16:20 Staginner 阅读(388) 评论(2) 推荐(0) 编辑
摘要: POJ_2182 没想到线段树也可以这么用,确实线段树太灵活了…… 这个题目可以转化成从后向前依次查询,比如当前奶牛的前面有x个号码比它小的奶牛,那么它就应该在剩余的数的序列中排第x+1。因此,我们可以维护一个线段树,节点值表示当前区间内还有多少个数,当寻找第x+1大的数时,可以自顶向下查找,找到之后删去这个数,即自底向上更新一遍节点的值即可。#include<stdio.h>#include<string.h>#define MAXD 8010int tree[4 * MAXD], N, M, q[MAXD];void init(){ int i, j; memset 阅读全文
posted @ 2011-10-27 15:38 Staginner 阅读(389) 评论(0) 推荐(0) 编辑
上一页 1 ··· 63 64 65 66 67 68 69 70 71 ··· 85 下一页