HDU 4866 Shooting 题解:主席树
这题的主要的坑点就是他给你的射击目标有重合的部分,如果你向这些重合的部分射击的话要考虑两种情况:
射击目标数量 ≥ 重合数量 : 全加上
射击目标数量 ≤ 重合数量 : 只加距离*射击目标数量
然而这题的内存还是很良心的,总体比较水吧。
主要做法是按照横坐标1~x建立主席树,每棵主席树维护l,r区间的设计目标数量,以及这些数量如果全部被射击获得的分数,这些在建树的时候是很好维护的。
然后对这些线段的处理要用扫描线的思想,就(左端点)建立一个(+1)的入点,(右端点+1)的位置建立一个(-1)的出点,然后从左往右扫一遍即可。
具体过程见代码:
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
#define INF 2*0x3f3f3f3f using namespace std; int n, m, x, p; struct N { int ls, rs, w; long long sum; } tree[6000100];
int roots[200010];
int b[200010], tot, cnt; int build_tree(int l, int r) {
int newnode = tot++;
tree[newnode].w = 0;
tree[newnode].sum = 0;
if (l != r) {
int mid = (l + r) / 2;
tree[newnode].ls = build_tree(l, mid);
tree[newnode].rs = build_tree(mid + 1, r);
}
return newnode;
} int updata(int rt, int pos, int val) {
int newnode = tot++, tmp = newnode;
long long add = b[pos - 1];
tree[newnode].sum = tree[rt].sum + add * val;
tree[newnode].w = tree[rt].w + val;
int l = 1, r = cnt;
while (l < r) {
int mid = (l + r) / 2;
if (pos <= mid) {
tree[newnode].ls = tot++;
tree[newnode].rs = tree[rt].rs;
newnode = tree[newnode].ls;
rt = tree[rt].ls;
r = mid;
}
else {
tree[newnode].ls = tree[rt].ls;
tree[newnode].rs = tot++;
newnode = tree[newnode].rs;
rt = tree[rt].rs;
l = mid + 1;
}
tree[newnode].sum = tree[rt].sum + add * val;
tree[newnode].w = tree[rt].w + val;
}
return tmp;
} long long query(int rt, int k) {
//printf("rt = %d k = %d\n",rt,k);
int l = 1, r = cnt;
long long ans = 0;
while (l < r) {
int mid = (l + r) / 2;
int tmp = tree[tree[rt].ls].w;
if (tmp >= k) {
rt = tree[rt].ls;
r = mid;
}
else {
k -= tmp;
ans += tree[tree[rt].ls].sum;
rt = tree[rt].rs;
l = mid + 1;
}
}
if (tree[rt].w != 0)
ans += tree[rt].sum / tree[rt].w * min(k, tree[rt].w);
return ans;
} struct P {
int x, y, val;
P() {}
P(int _x, int _y, int _val) : x(_x), y(_y), val(_val) {}
bool operator < (const P &rhs) const {
return x < rhs.x;
}
} pois[500010]; void print(int rt, int l = 1, int r = cnt) {
printf("l = %d r = %d w = %d sum = %I64d\n", l, r, tree[rt].w, tree[rt].sum);
if (l != r) {
int mid = (l + r) / 2;
print(tree[rt].ls, l, mid);
print(tree[rt].rs, mid + 1, r);
}
} int main() {
//freopen("in.in", "r", stdin);
//freopen("out.out", "w", stdout);
while (scanf("%d %d %d %d", &n, &m, &x, &p) != EOF) {
int l1, l2, d;
int ps = 0;
for (int i = 0; i < n; i++) {
scanf("%d %d %d", &l1, &l2, &d);
b[i] = d;
pois[ps++] = P(l1, d, 1);
pois[ps++] = P(l2 + 1, d, -1);
}
sort(b, b + n);
cnt = unique(b, b + n) - b; sort(pois, pois + ps); tot = 0;
roots[0] = build_tree(1, cnt);
int t = 0;
for (int i = 1; i <= x; i++) {
roots[i] = roots[i - 1];
while (t < ps && pois[t].x == i) {
int tmp = (int)(lower_bound(b, b + cnt, pois[t].y) - b) + 1;
roots[i] = updata(roots[i], tmp, pois[t].val);
t++;
}
}
/*
for (int i = 1; i <= x; i++) {
printf("**********************tree %d is : \n", i);
print(roots[i]);
}
*/ long long now = 1;
int xs, as, bs, cs;
for (int i = 0; i < m; i++) {
//printf("i = %d\n", i);
scanf("%d %d %d %d", &xs, &as, &bs, &cs);
long long tmp = query(roots[xs], (now * as + bs) % cs);
if (now > p) tmp *= 2;
printf("%I64d\n", tmp);
now = tmp;
}
}
return 0;
}
HDU 4866 Shooting 题解:主席树的更多相关文章
- HDU 4866 Shooting(主席树)题解
题意:在一个射击游戏里面,游戏者可以选择地面上[1,X]的一个点射击,并且可以在这个点垂直向上射击最近的K个目标,每个目标有一个价值,价值等于它到地面的距离.游戏中有N个目标,每个目标从L覆盖到R,距 ...
- HDU 4866 Shooting (主席树)
题目链接 HDU 4866 题意 给定$n$条线段.每条线段平行$x$轴,离x轴的距离为$D$,覆盖的坐标范围为$[L, R]$. 现在有$m$次射击行动,每一次的射击行动可以描述为在横坐标$ ...
- HDU 4866 Shooting 扫描线 + 主席树
题意: 在二维平面的第一象限有\(n(1 \leq n \leq 10^5)\)条平行于\(x\)轴的线段,接下来有\(m\)次射击\(x \, a \, b \, c\). 每次射击会获得一定的分数 ...
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- HDU 5919 Sequence II 主席树
Sequence II Problem Description Mr. Frog has an integer sequence of length n, which can be denoted ...
- HDU - 2665 Kth number 主席树/可持久化权值线段树
题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...
- hdu 2665 Kth number 主席树
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Prob ...
- HDU 4417 Super Mario 主席树
分析:找一个区间里小于等于h的数量,然后这个题先离散化一下,很简单 然后我写这个题主要是熟悉一下主席树,其实这个题完全可以离线做,很简单 但是学了主席树以后,我发现,在线做,一样简单,而且不需要思考 ...
- hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)
题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...
随机推荐
- java基础学习笔记五(抽象类)
java基础学习总结——抽象类 抽象类介绍
- Vue项目中导入excel文件读取成js数组
1. 安装组件 cnpm install xlsx --save 2. 代码 <template> <span> <input class="input-fil ...
- Qt 无法连接mysql数据库的问题
错误信息: QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL ...
- 探索Redis设计与实现14:Redis事务浅析与ACID特性介绍
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- 探索Redis设计与实现5:Redis内部数据结构详解——quicklist
本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...
- ES6数组方法
ES6数组方法 以下方法添加到了Array.prototype对象上(isArray除外) indexOf 类似字符串的indexOf()方法 stringObject.indexOf(searchv ...
- C#基本语法1 ----> 实例
| 版权声明:本文为博主原创文章,未经博主允许不得转载. ///////////////////////////////////////////////////////////////////// ...
- SQL中to_char方法的应用
1.取得当前日期是本月的第几周 SQL> select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; ----------------- ...
- 27-python基础-python3-异常处理(try except)
到目前为止,在 Python 程序中遇到错误,或“异常”,意味着整个程序崩溃.不希望这发生在真实世界的程序中. 相反,希望程序能检测错误,处理它们,然后继续运行. 实例1: 当试图用一个数除以零时 ...
- JS鼠标效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...