上一页 1 ··· 29 30 31 32 33 34 35 36 37 ··· 85 下一页
  2012年4月7日
摘要: POJ_2991 如果我们将其中某一个线段旋转β角,那么这个线段上方的所有线段都会旋转β角,这就很类似线段树中的对区间加上一个常数的问题了,于是不妨向着线段树的思路去想。 接下来一个问题就是β角是相对于谁的,换句话说我们所谓的每个线段都会旋转β角,那么是绕谁旋转的?实际上,如果我们局限于把线段当线段看的话,那么这个旋转就会看成是绕某个定点的,这个点就是我们旋转的线段和它下面那个不动的线段的交点,再这样想下去我们就没法处理了,因为每个旋转操作所绕的定点不是唯一的,我们没办法把所有的旋转操作都统一到一起,那么我们就没办法把旋转操作叠加,这样就没法使用线段树了。 但如果换个思路的话,实际上β角还等于 阅读全文
posted @ 2012-04-07 20:27 Staginner 阅读(2051) 评论(0) 推荐(1) 编辑
  2012年4月6日
摘要: POJ_1436 这个题目最后统计的时候直接暴力即可,一开始想的时候以为这样过不了的,没想到大家都是暴力统计的……而且我用“优化”后的局部O(nlogn)的统计方式(注释部分的代码),反倒没有局部O(n^2)的统计方式快,看来真正horizontally visible的线段对确实比较少。 至于查询的过程,我们可以先把线段按x排序,然后逐一扫描,查询每个线段的下面还有哪些线段是可以“看得到”的,查询完之后再把线段所在的区间染色即可。 此外,由于如果我们将每个纵坐标看作一个区间的话,这样两个相邻的纵坐标之间就没有空当了,所以为了避免丢解,可以把线段的坐标全部乘以2,这样奇数的坐标就表示了两个纵坐 阅读全文
posted @ 2012-04-06 17:51 Staginner 阅读(272) 评论(0) 推荐(0) 编辑
摘要: POJ_3225 对于开区间还是闭区间的问题,可以把所有的点都乘以2,这样就可以通过偶数端点判断是闭区间,通过奇数端点判断开区间。 剩下的问题就是用线段树实现区间染色和区间取反的操作了。#include<stdio.h>#include<string.h>#define MAXD 132000#define N 131070int tree[4 * MAXD], rev[4 * MAXD], to[4 * MAXD], a[MAXD];void build(int cur, int x, int y){ int mid = (x + y) >> 1, ls 阅读全文
posted @ 2012-04-06 11:19 Staginner 阅读(274) 评论(0) 推荐(0) 编辑
摘要: HDU_1698 直接用线段树对区间成段更新即可。#include<stdio.h>#include<string.h>#define MAXD 100010int N, M, flag[4 * MAXD], sum[4 * MAXD];void build(int cur, int x, int y){ int mid = (x + y) >> 1, ls = cur << 1, rs = (cur << 1) | 1; flag[cur] = 0, sum[cur] = 1; if(x == y) return ; build(l 阅读全文
posted @ 2012-04-06 01:48 Staginner 阅读(200) 评论(0) 推荐(0) 编辑
  2012年4月5日
摘要: POJ_2886 由于N比较大,如果像模拟约瑟夫环那样用链表模拟的话,每次查找操作的复杂度是O(N)的,时间上是不允许的。但如果我们用线段树来直接求每次轮到谁的话,每次就只需要O(logN)的时间了。 于是大概思路就是每次都通过线段树查找相应的位置,然后计算一下F(p)的值并更新结果即可。#include<stdio.h>#include<string.h>#include<math.h>#define MAXD 500010int N, M, K, P, tree[4 * MAXD], card[MAXD], isprime[MAXD], prime[MA 阅读全文
posted @ 2012-04-05 23:56 Staginner 阅读(264) 评论(0) 推荐(0) 编辑
摘要: HDU_1394 这个题目可以根据现有的逆序数对,推出其余情况的逆序数对。 我们每次从开头拿走一个元素,就相当于减少了右边比他小的元素的数量这么多个逆序数对,而放到最后就相当于增加了左边比他大的元素的数量这么多个逆序数对,而这些值是可以用线段树与处理出来的。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 10000int N, M, tree[4 * MAXD], left[MAXD], right[MAXD];struct Point{ int x, y;}p[MAXD]; 阅读全文
posted @ 2012-04-05 14:29 Staginner 阅读(212) 评论(0) 推荐(0) 编辑
  2012年4月4日
摘要: HDU_2795 尽管h的范围很大,但有一个有效的优化就是如果h>n那么可以直接令h=n,因为即便每行只贴1张海报,最后也只会占n行。 之后就是将每行看成一个点,用线段树记录每行还剩多少空间即可。#include<stdio.h>#include<string.h>#define MAXD 200010int H, W, N, tree[4 * MAXD];void build(int cur, int x, int y){ int mid = (x + y) / 2, ls = 2 * cur, rs = 2 * cur + 1; tree[cur] = W; 阅读全文
posted @ 2012-04-04 21:59 Staginner 阅读(264) 评论(0) 推荐(0) 编辑
摘要: SGU_214 这个题目和最长公共子序列dp的过程是类似的,可以用f[i][j]表示λ匹配到i,μ匹配到j时的最优解。那么f[i][j]只会由三种情况得到:一种情况是λ[i]和某个字符去匹配(显然应该和匹配后增加的值最小的字符去匹配),一种情况是μ[j]和某个字符去匹配(也应该和匹配后增加的值最小的字符去匹配),还有一种情况是λ[i]和μ[j]匹配。#include<stdio.h>#include<string.h>#define MAXD 2010#define INF 0x7fffffffchar a[MAXD], b[MAXD], alph[300];long 阅读全文
posted @ 2012-04-04 00:13 Staginner 阅读(427) 评论(0) 推荐(0) 编辑
  2012年4月3日
摘要: POJ_3245 这个题目和POJ_3017很像,不过已知的限制条件和求的东西反过来了。 这个题目其实读起来挺费劲的,不过结合他给的HINT还算理解了,建议大家不要去看第一段那几个表达式了,我越看越晕,不知道他在说什么,只要知道分成的几组必须是连续的就行了,然后就可以无视第一段了。 对于第一个限制条件,实际上就是要求对于所有的p<q,且p和q不分在一组,那么必须有Bp>Aq,换句话讲,如果存在p<q且Bp<=Aq,那么p和q就必须分在一组,这样我们就可以把必须分到一起的点连同他们之间的那些点合并看成一个点,然后用sum{Bi}作为这个点的B,用max{Ai}作为这个点的 阅读全文
posted @ 2012-04-03 14:24 Staginner 阅读(607) 评论(0) 推荐(0) 编辑
  2012年4月2日
摘要: POJ_3378 如果设f[i][j]表示第i个数选a[j]时的方案数,那么f[i][j]就等于所有满足a[k]<a[j]的f[i-1][k]之和,为了能够快速的求出这个和,可以在循环i-1的时候就将所有的f[i-1][k]放到线段树、树状数组或者平衡树上去即可。如果用线段树或者树状数组统计的话,需要将a[]的值离散化。 此外,在计算中间结果时5000^4是不会超long long的,但是最后合并的时候需要用到高精度加法。#include<stdio.h>#include<string.h>#include<stdlib.h>#define MAXD 阅读全文
posted @ 2012-04-02 19:05 Staginner 阅读(328) 评论(0) 推荐(0) 编辑
上一页 1 ··· 29 30 31 32 33 34 35 36 37 ··· 85 下一页