poj 2464(区间更新)
来源:互联网 发布:网络喷子到底是哪些人 编辑:程序博客网 时间:2024/06/08 22:41
题意:给出n个点的坐标,Stan和Ollie玩游戏,Stan会先选一个点过这个点画一条竖直的线,然后Ollie会在这条竖直的线上过一个点画一条横线,然后平面分成了四部分,Stan会将第一和第三象限上的点的数量作为自己的分数,Ollie会将第二和第四象限上的点的数量作为自己的分数,线上的点不计,Stan会采用让自己最小分数最大的方案去选择画竖线,Ollie会选择让自己分数更多的方案划线,要求输出Stan的最大的最小分数,然后输出在这种情况下的所有Ollie的分数,按升序排列。
题解:这题其实用树状数组写会更好,但是这里用了线段树,思路来自这位http://blog.csdn.net/shiqi_614/article/details/8236745,分别用两个线段树tree1和tree2维护Stan和Ollie的分数,把y坐标离散化,然后按x坐标从小到大排序,把每个y的上方有多少个点和下方有多少个点都统计并作为线段树初始值,然后从最左边的点开始扫描,所有x相同的点,用修改函数要把这些点从两个树内删除,因为线上的点不计,然后查询这些点的值更新结果,然后把这些点再加入线段树方便下一个x的查询。
#include <cstdio>#include <cstring>#include <algorithm>#include <map>#include <vector>using namespace std;const int N = 200005;const int INF = 0x3f3f3f3f;struct Point { int x, y; bool operator < (const Point &a) const { return x < a.x; }}p[N];int n, tree1[N << 2], tree2[N << 2], numh[N], numl[N], res1;vector<int> a, b, res2;map<int, int> mp;void pushdown(int k) { tree1[k * 2] += tree1[k]; tree1[k * 2 + 1] += tree1[k]; tree2[k * 2] += tree2[k]; tree2[k * 2 + 1] += tree2[k]; tree1[k] = tree2[k] = 0;}void build(int k, int left, int right) { tree1[k] = tree2[k] = 0; if (left == right) { tree1[k] = numh[left]; tree2[k] = numl[left]; return; } int mid = (left + right) / 2; build(k * 2, left, mid); build(k * 2 + 1, mid + 1, right);}void modify(int k, int left, int right, int l, int r, int flag, int v) { if (l <= left && right <= r) { if (flag == 1) tree1[k] += v; else tree2[k] += v; return; } pushdown(k); int mid = (left + right) / 2; if (l <= mid) modify(k * 2, left, mid, l, r, flag, v); if (r > mid) modify(k * 2 + 1, mid + 1, right, l, r, flag, v);}void query(int k, int left, int right, int pos, int& temp1, int& temp2) { if (left == right) { temp1 = tree1[k]; temp2 = tree2[k]; return; } pushdown(k); int mid = (left + right) / 2; if (pos <= mid) query(k * 2, left, mid, pos, temp1, temp2); else query(k * 2 + 1, mid + 1, right, pos, temp1, temp2);}int main() { while (scanf("%d", &n) == 1 && n) { a.clear(), b.clear(), mp.clear(), res2.clear(); for (int i = 0; i < n; i++) { scanf("%d%d", &p[i].x, &p[i].y); a.push_back(p[i].y); } sort(p, p + n); sort(a.begin(), a.end()); b.push_back(a[0]); int m = 0; numl[m] = 0; mp[a[0]] = 0; for (int i = 0; i < n; i++) { if (b[m] != a[i]) { numh[m] = n - i; numl[++m] = i; b.push_back(a[i]); mp[b[m]] = m; } } numh[m] = 0; build(1, 0, m); res1 = 0; for (int cur1 = 0; cur1 < n;) { int cur2 = cur1; while (cur2 < n && p[cur1].x == p[cur2].x) { if (p[cur2].y != b[0]) modify(1, 0, m, mp[b[0]], mp[p[cur2].y] - 1, 1, -1); if (p[cur2].y != b[m]) modify(1, 0, m, mp[p[cur2].y] + 1, mp[b[m]], 2, -1); cur2++; } int maxx = 0, minn = INF; for (int i = cur1; i < cur2; i++) { int temp1, temp2; query(1, 0, m, mp[p[i].y], temp1, temp2); minn = min(minn, temp1); maxx = max(maxx, temp2); } if (minn == res1) res2.push_back(maxx); else if (minn > res1) { res1 = minn; res2.clear(); res2.push_back(maxx); } for (int i = cur1; i < cur2; i++) { if (p[i].y != b[0]) modify(1, 0, m, mp[b[0]], mp[p[i].y] - 1, 2, 1); if (p[i].y != b[m]) modify(1, 0, m, mp[p[i].y] + 1, mp[b[m]], 1, 1); } cur1 = cur2; } sort(res2.begin(), res2.end()); res2.erase(unique(res2.begin(), res2.end()), res2.end()); printf("Stan: %d; Ollie:", res1); int sz = res2.size(); for (int i = 0; i < sz; i++) printf(" %d", res2[i]); printf(";\n"); } return 0;}
0 0
- poj 2464(区间更新)
- poj 2991(区间更新)
- POJ 3468(区间更新)
- POJ 3667 Hotel 区间合并+区间更新
- POJ 3468(区间更新,求和)
- POJ 3237 Tree(树链剖分 + 单点更新 + 区间更新 + 区间查询)
- POJ 3468 线段树 区间更新
- POJ-3468(线段树_区间更新)
- 线段树 : 区间更新 poj 3468 示例
- 线段树 : 区间更新 poj 3468 示例
- poj 2528 Mayor's posters (区间更新)
- poj 3468 线段树区间更新维护
- poj 2528 线段树区间更新
- poj 2528(线段树区间更新)
- poj 3468 线段树区间更新
- poj 2777 线段树区间更新
- poj 3468(简单线段树区间更新)
- poj 2991 线段树区间更新
- 一元线性回归(原理)
- ps笔记
- uva 11526 H(n)
- PE格式详细讲解10 – 基址重定位
- 【Android】2015.09.08 第一行代码 Day6 Count:8
- poj 2464(区间更新)
- zookeeper集群安装配置
- Ibatis和myIbatis 返回插入的主键ID
- windows下mysql5.1忘记root密码解决方法[win7]
- Unity中的网络编程
- 工作中感受到的消息中间件在分布式系统中的使用场景
- jQuery插件开发
- mysql函数之——控制流函数
- 30岁之前的目标是什么?