BZOJ 3833 [POI 2014] Solar Lamps 解题报告
来源:互联网 发布:谷歌浏览器禁止js 编辑:程序博客网 时间:2024/06/06 01:30
相信大家都是看了题才来看题解的
所以我就不发题面了=_=
不如当一个萌萌哒链接菌吧=_=
毕竟我懒=_=
题目传送门
Solution
卧槽。【总领全文,奠定感情基调】
首先我们可以进行坐标变换。
如果两个向量构成一组基底,
我们可以把平面内每个的坐标
使得:
于是我们可以求得
然后我们发现这些坐标都是分数,
而且最重要的是:分母都是一样的。
于是我们可以令所有的坐标都乘以这个分母(要保证乘的是正的数字)。
于是我们就可以离散化这些点的坐标,使得坐标范围变成一个
于是再给点以
并按照这个顺序处理那些点。
这样我们后面的点的
就可以不用管这一维了,只用管
于是我们假设处理到第
令
那么
特别的,如果那个矩阵中没有
于是怎么维护呢?
【插入操作】
我们以时间为
每次插入都会在
于是插入操作的时间复杂度是
【查询操作】
怎么查询以
我们可以二分答案。
具体做法就是从线段树根结点开始,先看左儿子所套的平衡树里边
设有
并且在以
如果
否则答案就应该在
直到
然后我们可以加上一个小优化:
如果递归处理到
那么直接返回
因为
如果可能的最小值都不比
查询操作中,我们要访问
所以查询操作的时间复杂度也是
然后有
每个灯泡的信息会被插入到
所以空间复杂度是
如果写矩形树(二维线段树)的话空间复杂度就是
所以才要写这种蛋疼的东西。。。
卧槽。【承上启下,推动情节发展】
等等。
我们好像忽略了一点:
如果灯的照射范围是一条线该怎么办。。。
啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊啊。。。
其实也比较好处理。
我们把另一个向量弄成垂直于当前的这条向量。
可以令 :
然后也可以求出点的
只不过在查询的时候,我们找的就不是矩阵中点的个数,
而是某一条线段里边的点的个数了。
稍微处理一下就可以了。。。=_=
具体实现可以看我的代码。
卧槽。【总结全文,升华文章主旨】
毕竟
#include <cmath>#include <cstdio>#include <vector>#include <cstdlib>#include <cstring>#include <iostream>#include <algorithm>using namespace std;typedef long long LL;#define N 200000 + 5#define M 524288 + 5#define SIZE 5000000 + 5#define ls(x) x << 1#define rs(x) x << 1 | 1int n, tot, Ord[N], Root[M], Ans[N], K[N];LL x_1, y_1, x_2, y_2, X[N], Y[N], _X[N], _Y[N];struct Data{ int l, r, fa, size, num, fix;}h[SIZE];inline void update(int x){ h[x].size = h[h[x].l].size + h[h[x].r].size + h[x].fix;}inline void zig(int x){ int y = h[x].fa, z = h[y].fa; if (y == h[z].l) h[z].l = x; if (y == h[z].r) h[z].r = x; h[x].fa = z, h[y].fa = x; h[y].l = h[x].r, h[h[x].r].fa = y, h[x].r = y; update(y), update(x);}inline void zag(int x){ int y = h[x].fa, z = h[y].fa; if (y == h[z].l) h[z].l = x; if (y == h[z].r) h[z].r = x; h[x].fa = z, h[y].fa = x; h[y].r = h[x].l, h[h[x].l].fa = y, h[x].l = y; update(y), update(x);}inline void Splay(int &root, int x){ while (h[x].fa) { int y = h[x].fa, z = h[y].fa; if (x == h[y].l) { if (y == h[z].l) zig(y); zig(x); } else { if (y == h[z].r) zag(y); zag(x); } } root = x;}inline void Insert(int &root, int u){ if (!root) { root = ++ tot; h[tot].size = h[tot].fix = 1, h[tot].num = u; return ; } int z, p = root; while (p) { z = p; h[z].size ++; if (u == h[z].num) { h[z].fix ++; return ; } if (u > h[z].num) p = h[z].r; else p = h[z].l; } h[++ tot].fix = 1; h[tot].size = 1; h[tot].num = u; h[tot].fa = z; if (u > h[z].num) h[z].r = tot; else h[z].l = tot; Splay(root, tot);}inline int Find(int x, int k, bool op){ int res = 0; while (1) { if (!x) { if (op) return 0; break ; } if (k == h[x].num) { if (op) return h[x].fix; res += h[h[x].l].size + h[x].fix; break ; } else if (k > h[x].num) { res += h[h[x].l].size + h[x].fix; x = h[x].r; } else x = h[x].l; } return res;}inline int Query(int x, int l, int r, int k, int lim, int Lim, bool op){ if (l >= Lim) return Lim; if (l == r) return l; int mid = l + r >> 1; int t = Find(Root[ls(x)], lim, op); if (k <= t) return Query(ls(x), l, mid, k, lim, Lim, op); else return Query(rs(x), mid + 1, r, k - t, lim, Lim, op);}inline void Modify(int x, int l, int r, int t, int k){ Insert(Root[x], k); if (l == r) return ; int mid = l + r >> 1; if (t <= mid) Modify(ls(x), l, mid, t, k); else Modify(rs(x), mid + 1, r, t, k);}inline int getint(){ char ch = '\n'; for (; ch != '-' && (ch > '9' || ch < '0'); ch = getchar()) ; int f = ch == '-' ? -1 : 1; int res = ch == '-' ? 0 : ch - '0'; for (ch = getchar(); ch >= '0' && ch <= '9'; ch = getchar()) res = (res << 3) + (res << 1) + ch - '0'; return res * f;}inline bool cmp(int u, int v){ return X[u] < X[v] || (X[u] == X[v] && Y[u] < Y[v]);}inline void Solve(bool op){ if (op) x_2 = -y_1, y_2 = x_1; int f = (x_2 * y_1 - x_1 * y_2 > 0) ? 1 : -1; for (int i = 1; i <= n; i ++) { LL u = getint(), v = getint(); _X[i] = X[i] = (x_2 * v - y_2 * u) * f; _Y[i] = Y[i] = (y_1 * u - x_1 * v) * f; } sort(_X + 1, _X + n + 1); sort(_Y + 1, _Y + n + 1); int sx = unique(_X + 1, _X + n + 1) - _X; int sy = unique(_Y + 1, _Y + n + 1) - _Y; for (int i = 1; i <= n; i ++) { int u = lower_bound(_X + 1, _X + sx, X[i]) - _X; int v = lower_bound(_Y + 1, _Y + sy, Y[i]) - _Y; X[i] = u, Y[i] = v; Ord[i] = i, K[i] = getint(); } sort(Ord + 1, Ord + n + 1, cmp); for (int i = 1; i <= n; i ++) { int _i = Ord[i]; if (Find(Root[1], Y[_i], op) < K[_i]) Ans[_i] = _i; else Ans[_i] = Query(1, 1, n, K[_i], Y[_i], _i, op); Modify(1, 1, n, Ans[_i], Y[_i]); }}int main(){ #ifndef ONLINE_JUDGE freopen("3833.in", "r", stdin); freopen("3833.out", "w", stdout); #endif n = getint(); x_1 = getint(), y_1 = getint(); x_2 = getint(), y_2 = getint(); Solve(x_1 * y_2 == x_2 * y_1); for (int i = 1; i <= n; i ++) printf("%d%c", Ans[i], " \n"[i == n]); return 0;}
- BZOJ 3833 [POI 2014] Solar Lamps 解题报告
- bzoj 3833 [Poi2014]Solar lamps 树套树 splay
- BZOJ 2079 [Poi 2010] 图论 解题报告
- BZOJ 1131 [POI 2008] 解题报告
- USACO :Party Lamps解题报告
- BZOJ3833: [Poi2014]Solar lamps
- BZOJ3833[Poi2014] Solar lamps
- POI2014 Solar Lamps
- BZOJ3833: [Poi2014]Solar lamps
- [POI 2014]Solar Panels(数论)
- BZOJ 2792 [POI 2012] 二分答案 解题报告
- BZOJ 1116 [POI 2008] 并查集 解题报告
- BZOJ 1103 [POI 2007] dfs序+树状数组 解题报告
- BZOJ 2527 [Poi 2011] 整体二分 解题报告
- BZOJ 1097 [POI 2007] SPFA+状压DP 解题报告
- BZOJ 4726 [POI 2017] 树DP 解题报告
- BZOJ 2212 [Poi 2011] 线段树合并 解题报告
- BZOJ 1529 [POI 2005] 并查集 解题报告
- [BZOJ 1064][NOI 2008]假面舞会(图论+BFS)
- Cocos2d-x 3.2 onEnter与onEnterTransitionDidFinish的区别
- 黑马程序员--06OC类和对象
- poj 1330 Nearest Common Ancestors
- Codeforces 337E Divisor Tree 暴搜
- BZOJ 3833 [POI 2014] Solar Lamps 解题报告
- Java并发的四种风味:Thread、Executor、ForkJoin和Actor
- ECMAScript的数据类型(1)
- Smarty----注册一个函数以plugins方式
- Https握手(验证证书->交换密钥) 证书防伪造(签名验证), 防篡改(签名验证),防替换(域名验证),防假冒(解不开密钥)
- 数据库中如何写视图,以及视图项目中实际应用
- USACO1.1--Your Ride Is Here +水题
- 函数嵌套 创建枚举和声明接口
- PHP利用curl抓取密码功能