这题的主要的坑点就是他给你的射击目标有重合的部分,如果你向这些重合的部分射击的话要考虑两种情况:

射击目标数量 ≥ 重合数量 : 全加上

射击目标数量 ≤ 重合数量 : 只加距离*射击目标数量

然而这题的内存还是很良心的,总体比较水吧。

主要做法是按照横坐标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 题解:主席树的更多相关文章

  1. HDU 4866 Shooting(主席树)题解

    题意:在一个射击游戏里面,游戏者可以选择地面上[1,X]的一个点射击,并且可以在这个点垂直向上射击最近的K个目标,每个目标有一个价值,价值等于它到地面的距离.游戏中有N个目标,每个目标从L覆盖到R,距 ...

  2. HDU 4866 Shooting (主席树)

    题目链接  HDU 4866 题意  给定$n$条线段.每条线段平行$x$轴,离x轴的距离为$D$,覆盖的坐标范围为$[L, R]$.   现在有$m$次射击行动,每一次的射击行动可以描述为在横坐标$ ...

  3. HDU 4866 Shooting 扫描线 + 主席树

    题意: 在二维平面的第一象限有\(n(1 \leq n \leq 10^5)\)条平行于\(x\)轴的线段,接下来有\(m\)次射击\(x \, a \, b \, c\). 每次射击会获得一定的分数 ...

  4. HDU 4866 Shooting(持久化线段树)

    view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...

  5. HDU 5919 Sequence II 主席树

    Sequence II Problem Description   Mr. Frog has an integer sequence of length n, which can be denoted ...

  6. HDU - 2665 Kth number 主席树/可持久化权值线段树

    题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...

  7. hdu 2665 Kth number 主席树

    Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Prob ...

  8. HDU 4417 Super Mario 主席树

    分析:找一个区间里小于等于h的数量,然后这个题先离散化一下,很简单 然后我写这个题主要是熟悉一下主席树,其实这个题完全可以离线做,很简单 但是学了主席树以后,我发现,在线做,一样简单,而且不需要思考 ...

  9. hdu 5919--Sequence II(主席树--求区间不同数个数+区间第k大)

    题目链接 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2 ...

随机推荐

  1. java基础学习笔记五(抽象类)

    java基础学习总结——抽象类 抽象类介绍

  2. Vue项目中导入excel文件读取成js数组

    1. 安装组件 cnpm install xlsx --save 2. 代码 <template> <span> <input class="input-fil ...

  3. Qt 无法连接mysql数据库的问题

    错误信息: QSqlDatabase: QMYSQL driver not loaded QSqlDatabase: available drivers: QSQLITE QMYSQL QMYSQL ...

  4. 探索Redis设计与实现14:Redis事务浅析与ACID特性介绍

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  5. 探索Redis设计与实现5:Redis内部数据结构详解——quicklist

    本文转自互联网 本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial ...

  6. ES6数组方法

    ES6数组方法 以下方法添加到了Array.prototype对象上(isArray除外) indexOf 类似字符串的indexOf()方法 stringObject.indexOf(searchv ...

  7. C#基本语法1 ----> 实例

    |   版权声明:本文为博主原创文章,未经博主允许不得转载. ///////////////////////////////////////////////////////////////////// ...

  8. SQL中to_char方法的应用

    1.取得当前日期是本月的第几周 SQL> select to_char(sysdate,'YYYYMMDD W HH24:MI:SS') from dual; ----------------- ...

  9. 27-python基础-python3-异常处理(try except)

    到目前为止,在 Python 程序中遇到错误,或“异常”,意味着整个程序崩溃.不希望这发生在真实世界的程序中. 相反,希望程序能检测错误,处理它们,然后继续运行.   实例1: 当试图用一个数除以零时 ...

  10. JS鼠标效果

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...