【16.50%】【CF 44G】Shooting Gallery
来源:互联网 发布:数控车床手工编程入门 编辑:程序博客网 时间:2024/06/03 17:31
【题解】
意思是说每个靶子离射击点的距离为z.然后描述矩形靶子的左下角和右下角。
射击m次。每次射击靶子之后。靶子会毁坏(假如同一个点有多个靶子重叠,最前面那个靶子坏掉。其他靶子还可以射击);
做法:
给每个子弹记录三个信息x,y,bianhao。即坐标以及各个子弹出现的先后顺序。
然后以靶子离射击点的距离为关键字从小到大排序。
处理第一个靶子是被哪一个子弹射击了。即在靶子所在范围内的子弹。且要求子弹的编号(射击顺序)最小。
这个问题可以用kd-tree来解决。
以子弹的点为元素建立kdtree
知道一个靶子是被哪个子弹射击之后。在kdtree中删掉这个子弹。然后继续处理下一个靶子。
编程复杂度很高。
【代码】
#include <cstdio>#include <algorithm>using namespace std;const int MAXN = 105000;const int INF = 2100000000;struct target{int mi_n[2], ma_x[2], z, n;};struct point{int min, n, dot, d[2],fa,l,r;};int n, m, root, now, txl, txr, tyl, tyr, ans[MAXN] = { 0 };target rec[MAXN];point t[MAXN];void input_data(){scanf("%d", &n);for (int i = 1; i <= n; i++){scanf("%d%d%d%d%d", &rec[i].mi_n[0], &rec[i].ma_x[0], &rec[i].mi_n[1], &rec[i].ma_x[1], &rec[i].z);rec[i].n = i;}scanf("%d", &m);for (int i = 1; i <= m; i++){scanf("%d%d", &t[i].d[0], &t[i].d[1]);t[i].n = i;}}bool cmp_1(point a, point b){return a.d[now] < b.d[now];}void gengxin(int father, int son){if (t[father].min > t[son].min){t[father].min = t[son].min;t[father].dot = t[son].dot;}}void up_data(int rt){t[rt].min = t[rt].n; t[rt].dot = rt; //dot可以说是当前这个子树的编号最小的点的节点。if (t[rt].n == 0) //如果点已经删掉了{t[rt].min = INF;t[rt].dot = 0;}int l = t[rt].l, r = t[rt].r;if (l)gengxin(rt, l);if (r)gengxin(rt, r);}int build(int begin, int end, int fa,int fx){int m = (begin + end) >> 1;now = fx;nth_element(t + begin, t + m, t + end + 1, cmp_1);t[m].fa = fa;if (begin < m)t[m].l = build(begin, m - 1, m, 1 - fx);if (m < end)t[m].r = build(m + 1, end, m, 1 - fx);up_data(m);return m;}bool inrange(int x, target b,int fx){return ((b.mi_n[fx] <= x) && (x <= b.ma_x[fx]));}int query(int rt, int fx, int r, int xl, int xr, int yl, int yr){//r是当前处理的靶子编号 txl,txr,tyl,tyr是靶子信息。//xl,xr,yl,yr是当前kd-tree的节点所在子树的所有点的范围(如果不确定就写成无穷大)if (!rt)//我们会不断缩小这个范围。return 0;if (!t[rt].dot)return 0;if (txl <= xl && xr <= txr && tyl <= yl && yr <= tyr)return t[rt].dot;int t1 = 0,t2 = 0;if (inrange(t[rt].d[fx], rec[r], fx))//这个节点的fx坐标在靶子范围内{ //则左右儿子都要递归求解。则后序还要查看当前这个节点是否能更新。if (fx == 0) //如果是以x轴排序{t1 = query(t[rt].l, 1-fx, r, xl, t[rt].d[0], yl, yr);t2 = query(t[rt].r, 1-fx, r, t[rt].d[0], xr, yl, yr);}else//以y轴排序{t1 = query(t[rt].l, 1-fx, r, xl, xr, yl, t[rt].d[1]);t2 = query(t[rt].r, 1-fx, r, xl, xr, t[rt].d[1], yr);}}else//这个靶子的xy坐标没有完全把这个点包住{//则只要返回左或右儿子if (t[rt].d[fx] < rec[r].mi_n[fx])//大于这个节点的fx坐标 等号的情况上面已经考虑了{if (fx == 0)return query(t[rt].r, 1-fx, r, t[rt].d[0], xr, yl, yr);elsereturn query(t[rt].r, 1-fx, r, xl, xr, t[rt].d[1], yr);}if (rec[r].ma_x[fx] < t[rt].d[fx])//小于这个节点的fx坐标{if (fx == 0)return query(t[rt].l, 1-fx, r, xl, t[rt].d[0], yl, yr);elsereturn query(t[rt].l, 1-fx, r, xl, xr, yl, t[rt].d[1]);}}int fi = 0; int temp = INF;if (t1!=0)if (t[t1].n < temp)//千万不要写成t[t1].min < temp{//因为可能t[t1].min对应的点不在我们所需的范围内 //这个rt就已经返回的是所需的节点的编号了,不要乱来temp = t[t1].n;fi = t1;}if (t2 != 0)if (t[t2].n < temp){temp = t[t2].n;fi = t2;}if (t[rt].n != 0 && t[rt].n < temp)//这是尝试用当前这个节点来更新。if (inrange(t[rt].d[0],rec[r],0) && inrange(t[rt].d[1],rec[r],1)){temp = t[rt].n;fi = rt;}return fi;}void adjust(int rt) //删掉一个点后调整相关点的信息{up_data(rt);if (rt != root)adjust(t[rt].fa);}bool cmp_2(target a, target b){return a.z < b.z;}void get_ans(){root = build(1, m, 0, 0);sort(rec + 1, rec + 1 + n, cmp_2);for (int i = 1; i <= n; i++){txl = rec[i].mi_n[0], txr = rec[i].ma_x[0], tyl = rec[i].mi_n[1], tyr = rec[i].ma_x[1];int hit = query(root, 0, i, 0, INF, 0, INF);if (hit != 0){ans[t[hit].n] = rec[i].n;t[hit].n = 0;adjust(hit);}}}void output_ans(){for (int i = 1; i <= m; i++)printf("%d\n", ans[i]);}int main(){//freopen("F:\\rush.txt", "r", stdin);input_data();get_ans();output_ans();return 0;}
0 0
- 【16.50%】【CF 44G】Shooting Gallery
- 【20.00%】【codeforces 44G】Shooting Gallery
- codeforces 30C - Shooting Gallery DP 概率
- CodeForces 30C Shooting Gallery 简单dp
- codeforces 30C Shooting Gallery (概率dp)
- CodeForces 30C — Shooting Gallery
- Codeforces 30C Shooting Gallery【dp】
- CF 618G
- Gallery g = (Gallery)findViewById(R.id.secondButton);
- G-Queue(CF-545D
- CF 549G排序,构造
- CF 589G 树状数组
- 0526 CF#96A&G2n G- Football
- CF 903G. Yet Another Maxflow Problem
- Gallery
- Gallery
- Gallery
- gallery
- Git和Egit安装使用总结
- 一些常见的运算符重载
- TOJ 2142.Pascal Library
- PHP如何实现网址伪静态
- 王学岗app架构设计-MVP
- 【16.50%】【CF 44G】Shooting Gallery
- 第44课:Spark 2.0编程实战之DataSet案例开发实战
- 工具类:ehCache,用于缓存
- 面试宝典第6章_ 2(const) const 成员函数 ,const 与define定义的不同
- PHP实现伪静态化页面的具体实现方式
- HDU 2028 Lowest Common Multiple Plus
- 机器学习中的数据清洗与特征处理综述
- java常用设计模式
- 【HDU 2255】【KM算法模板题+KM算法详解】 奔小康赚大钱