摘要: 先将高度值离散,映射到小范围,然后统计每个高度到下一个高度之间的总容积,最后从下到上不断模拟“填水”的过程。#include #include using namespace std;const int maxN = 50001;int n, v;double lev;int b[2*maxN], h[maxN], w[maxN], d[maxN], cx[2*maxN], cv[2*maxN];int *p[2*maxN];void input();void process();void compress(int *, int *);int cmp(const void *sa, const 阅读全文
posted @ 2014-02-23 16:51 莞中OI 阅读(250) 评论(0) 推荐(0)
摘要: 本题与《矩形面积》类似,只不过将点的个数变多,但点坐标的取值范围变小,并且每个点多了一个颜色属性而已。#include #include using namespace std;const int maxN = 1010;int n, m, a, b;int x[2*maxN], y[2*maxN], cx[2*maxN], cy[2*maxN];int *p[2*maxN];int map[2*maxN][2*maxN];int color[maxN], ans[2501];void input();void process();void compress(int *, int *);int 阅读全文
posted @ 2014-02-23 16:43 莞中OI 阅读(247) 评论(0) 推荐(0)
摘要: 离散思想的简单题目,只要掌握了离散思想,本题并不难。首先是快排,根据排序结果压缩横坐标和纵坐标,压缩后横纵坐标的最大值不大于 200,于是就可以用模拟的方法找到结果。#include #include using namespace std;int n, re;int x[200], y[200], c[100], tp[100];int *p[200];int map[200][200];void input();void process();void compress(int *);int cmp(const void *sa, const void *sb);int main(){ in 阅读全文
posted @ 2014-02-23 16:31 莞中OI 阅读(210) 评论(0) 推荐(0)
摘要: 先排序,再离散,然后模拟。问题是,排序之后,读入时的依赖关系就丢失了。比如读入时左下角坐标放在位置2*i,右上角坐标放在位置2*i+1;或者左下角坐标放在位置i,右上角坐标放在位置i+n。——这些就是依赖关系,排序之后,这些依赖关系可能就丢失了!怎么办?以X坐标为例,一种解决方法是,用P[i]表示X[P[i]] 的坐标,不要对原数组X[i]排序,而是对P[i]排序。对P[i]排序不是比较P[i],而是比较X[P[i]]。#include #include using namespace std;int n;__int64 re;int x[200], y[200], cx[200], cy[2 阅读全文
posted @ 2014-02-23 16:22 莞中OI 阅读(240) 评论(0) 推荐(0)
摘要: 比较明显的RMQ问题。对于给定的区间,需要快速回答出区间内的最大值和最小值。#include #include #define max(a, b) (((a)>(b))?(a):(b))#define min(a, b) (((a)<(b))?(a):(b))const int maxn = 10001;int n, m;int h[maxn];int dpmax[maxn][14], dpmin[maxn][14];int main(){ // input scanf("%d %d", &n, &m); for (int i=1; i<= 阅读全文
posted @ 2013-12-22 15:53 莞中OI 阅读(171) 评论(0) 推荐(0)
摘要: 经过分析,不难知道本题需要维护一个数据结构,使之支持以下操作:1. 合并战舰集合(M i j);2. 查询2艘战舰是否在同一集合/列(C i j);3. 如果在同一集合,求出它们的相对位置。标准的并查集只支持合并和查找操作,并不支持求集合中两元素之间相对距离的操作。所以我们要用扩展并查集。标准并查集中每个节点只有一个域,即用father[i] 表示节点 i 的父亲。本题可以扩展出两个域:用total[i] 表示以 i 为根的集合中的元素个数,它当且仅当i是根时有意义;用front[i] 表示排在 i 前面有多少个点,front[root]=0。若合并操作令 father[a] = b(a 和 阅读全文
posted @ 2013-12-20 16:34 莞中OI 阅读(357) 评论(0) 推荐(0)
摘要: 本题考察扩展并查集。对于这道题,多开辟一个数组来保存天敌关系怎么样?比如读入一个“天敌”关系的时候,就修改“天敌”数组的相应位置,但天敌又有天敌,处理当前天敌关系的时候,对于天敌的天敌是否也需要进行相应修改呢?其实本题有一种非常巧妙的做法,用一个数组father表示合并后的树,用数组rank表示节点和其父节点之间的关系。rank[x] 表示x与father[x]的关系:rank[x] = 0 表示x与 father[x] 是同类rank[x] = 1 表示x吃 father[x](等价于rank[x]=-2)rank[x] = 2 表示 father[x] 吃x(等价于rank[x]=-1)这 阅读全文
posted @ 2013-12-20 16:27 莞中OI 阅读(292) 评论(0) 推荐(0)
摘要: 矩形数目最多是7000,而本题时间限制是2秒,意味着即使用O(n2)级别的算法,也可以不超时。两重循环将矩形两两比较,如果出现重叠,就合并两个矩形,合并操作就用到并查集。关键是如何判断两个矩形重叠。#include typedef int POS;const int maxn = 7000;int n, ans;int pos[maxn][4];// left bottom right top x yint tree[maxn], rank[maxn];bool judge(POS i, POS j){ if (pos[i][0]pos[j][1]) return true; if (pos. 阅读全文
posted @ 2013-12-20 16:07 莞中OI 阅读(179) 评论(0) 推荐(0)
摘要: 当给出的数据无序的时候,不妨考虑先排序,排序以后或许能发现规律。本题正是要先对数据进行排序,不妨把所有公路按行驶速度从小到大排序。本题求最小速度比,由路径上的最大速度和最小速度决定。涉及两个要素的时候,不妨尝试通过枚举使一个要素固定下来。比如这道题,可以枚举最小速度。假如排序以后8条边如下:1 2 3 4 5 6 7 8先考虑最小速度取1的时候,最大速度取多少呢?2还是3?还是4?怎么找到最大速度呢?不难想到,只要把这些边从小到大依次加入,当加入某一条边的时候,出发点和目的地连通了,那最大速度就是这条边的权值。后面的边肯定不需要考虑了。然后再考虑最小速度取其他值的情况,如法炮制。原来这题就是考 阅读全文
posted @ 2013-12-19 20:10 莞中OI 阅读(257) 评论(0) 推荐(0)
摘要: 并查集的简单应用。Kruskal是求最小生成树的经典算法之一,如果忘记了,先做一下DGZX1042。Kruskal中每次挑选一条边加入最小生成树,就相当于将该边两个端点所在集合合并。#include #include #include #include using namespace std;int pa[3001];int rank[3001];int n, m;int ans;// answerint tot;// totalstruct node{ int x, y, z; };node tn[50000];int cmp(const void *pa, const void *pb){ 阅读全文
posted @ 2013-12-19 19:56 莞中OI 阅读(315) 评论(0) 推荐(0)