gym 101505 CTU Open Contest 2016 G Orchard Division
来源:互联网 发布:弗洛伊德算法例题 编辑:程序博客网 时间:2024/06/08 00:28
Problem
codeforces.com/gym/101505/attachments
vjudge.net/contest/187874#problem/G
Meaning
一个 m * m 的网格(长、宽下标 [ 0,m - 1])里有 n 个点,现要从四个角落中任意一个开始引出一个矩形,使得矩形内的点数恰好是总点数一半,且面积要尽量小,求这个最小面积,不存在输出 -1。
Analysis
枚举角落,以左下角为例。
从左到右枚举列(x),先一次性把该列的所有点全部加入考虑的“点集”,然后找当前的这个“点集”里按纵坐标 y 升序排的第
怎么维护这个“点集”可以快速找到第
至于枚举角落,可以把整个 m * m 的大矩阵做旋转(即把点的坐标做变换),就可以把其它角落都转化为左下角。
Code
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;const int N = 1e6, M = 1e9;struct pnt{ int x, y; pnt(int _x = 0, int _y = 0): x(_x), y(_y) {} bool operator < (const pnt &rhs) const { return x != rhs.x ? x < rhs.x : y < rhs.y; }} p[N];void rotate(int n, int m){ for(int i = 0, x; i < n; ++i) { x = p[i].x; p[i].x = m - 1 - p[i].y; p[i].y = x; }}int tree[N+7<<2];inline void pushup(int o){ tree[o] = tree[o<<1] + tree[o<<1|1];}void update(int y, int l, int r, int rt){ if(l == r) { ++tree[rt]; return; } int m = l + r >> 1; if(m < y) update(y, m + 1, r, rt<<1|1); else update(y, l, m, rt<<1); pushup(rt);}// 找第 k 个纵坐标int kth(int k, int l, int r, int rt){ if(l == r) return l; int m = l + r >> 1; if(tree[rt<<1] >= k) return kth(k, l, m, rt<<1); else return kth(k - tree[rt<<1], m + 1, r, rt<<1|1);}// 查询纵坐标区间的点数int query(int ql, int qr, int l, int r, int rt){ if(ql <= l && r <= qr) return tree[rt]; int res = 0, m = l + r >> 1; if(ql <= m) res += query(ql, qr, l, m, rt<<1); if(qr > m) res += query(ql, qr, m + 1, r, rt<<1|1); return res;}long long solve(int n, long long m){ // 离散化纵坐标 static int dsc[N]; for(int i = 0; i < n; ++i) dsc[i] = p[i].y; sort(dsc, dsc + n); int ny = unique(dsc, dsc + n) - dsc; sort(p, p + n); memset(tree, 0, sizeof tree); // 先直接插入前 n / 2 - 1 个点 for(int i = 0, y; i < n / 2 - 1; ++i) { y = lower_bound(dsc, dsc + ny, p[i].y) - dsc; update(y, 0, ny - 1, 1); } long long res = m * m; for(int i = n / 2 - 1, x, y, num; i < n; ) { // 把当前列所有点都插入 for(x = p[i].x; i < n && p[i].x == x; ++i) { y = lower_bound(dsc, dsc + ny, p[i].y) - dsc; update(y, 0, ny - 1, 1); } // 找第 n / 2 个纵坐标 y = kth(n>>1, 0, ny - 1, 1); // 检查矩形里是否恰好有 n / 2 个点 num = query(0, y, 0, ny - 1, 1); if(num << 1 == n) res = min(res, (dsc[y] + 1LL) * (x + 1LL)); } return res;}int main(){ int n, m; while(~scanf("%d%d", &m, &n)) { for(int i = 0; i < n; ++i) scanf("%d%d", &p[i].x, &p[i].y); // 奇数直接忽略 if(n & 1) { puts("-1"); continue; } long long ans = (long long)m * m; for(int i = 0; i < 4; ++i) { ans = min(ans, solve(n, m)); // 顺时针旋转矩阵 rotate(n, m); } if(ans >= (long long)m * m) ans = -1; printf("%I64d\n", ans); } return 0;}
阅读全文
0 0
- gym 101505 CTU Open Contest 2016 G Orchard Division
- Codeforces Gym 101505(2016-2017 CTU Open Contest) D---群论、模拟
- CTU open Contest 2016 Tree Stands
- CTU Open Contest 2016 Suspicious Samples
- CTU Open Contest 2016 Hot Air Ballooning
- CTU Open Contest 2016 Colorful Tribune(附测试数据)
- CTU Open Contest 2016 Suspicious Samples(单调队列)
- Codeforces Gym 101505D Orchard Division(离散化+树状数组+扫描线+二分)
- ACM ICPC 2017 Warmup Contest 7(CTU Open Contest 2016)
- ACM ICPC 2017 Warmup Contest 7(CTU Open Contest 2016)
- CTU Open Contest 2016 H. It's Raining, Man 模拟 分类讨论
- CTU Open 2013
- USACO 2015 US OPEN CONTEST,Silver Division Solution
- USACO 2015 US OPEN CONTEST,Gold Division Solution
- CF - gym - Samara University ACM ICPC 2016-2017 Quarterfinal Qualification Contest --- G
- CTU Open 2008(未完工)
- POJ1789【CTU Open 2003】Truck History
- CTU Open 1999 Lloyd Fifteen Puzzle
- android keystore 公钥,私钥,证书完全解析
- Eclipse下用Java连接MYSQL 数据库的连接步骤
- gson转json
- 命令执行漏洞
- idea 自动导入包 快捷键
- gym 101505 CTU Open Contest 2016 G Orchard Division
- exec 函数族
- class文件不能反编译
- Java消息中间件
- Ubuntu的LaTeX环境配置
- node.js+mongodb+redis+elasticsearch+koa2+pm2+atom 系统centos6.5
- 三段好玩的js代码
- SSH 的windows 与linux 的交互
- Message 机制 (java 层)