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

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

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

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

主要做法是按照横坐标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. Centos MySQL 5.7安装、升级教程

    MySQL 5.7安装.升级笔记分享: 卸载当前的 MySQL 查看当前 MySQL 版本: ? 1 2 [root@coderknock ~]# mysql -V mysql Ver 14.14 D ...

  2. 【Flutter学习】基本组件之上下刷新列表(一)

    一,概述 RefreshIndicator是Flutter基于Material设计语言内置的控件,集合了下拉手势.加载指示器和刷新操作一体,可玩性比FutureBuilder差了一大截,不过大家也用过 ...

  3. VC2010 CString.Format使用报错 error C2664

    error C2664: “void ATL::CStringT<BaseType,StringTraits>::Format(const wchar_t *,...)”: 不能将参数 1 ...

  4. 回调函数 和 promise对象,及封装API接口

    1.回调函数:https://blog.csdn.net/baidu_32262373/article/details/54969696 注意:回调函数不一定需要用到 return.如果浏览器支持Pr ...

  5. JAVA 的StringBuffer类

    StringBuffer类和String一样,也用来代表字符串,只是由于StringBuffer的内部实现方式和String不同,所以StringBuffer在进行字符串处理时,不生成新的对象,在内存 ...

  6. 为什么NULL能多次free

    void __cdecl _free_base (void * pBlock) {           int retval = 0;             if (pBlock == NULL) ...

  7. HTML5: HTML5 Geolocation(地理定位)

    ylbtech-HTML5: HTML5 Geolocation(地理定位) 1.返回顶部 1. HTML5 Geolocation(地理定位) HTML5 Geolocation(地理定位)用于定位 ...

  8. AutoFac控制反转 转载https://blog.csdn.net/u011301348/article/details/82256791

    一.AutoFac介绍 Autofac是.NET里IOC(Inversion of Control,控制反转)容器的一种,同类的框架还有Spring.NET,Unity,Castle等.可以通过NuG ...

  9. generate ascii table

    $ cat ascii.sh dec_count=0 while [ $dec_count -lt 256 ] do echo -e "\x$(echo "ibase=10;oba ...

  10. QT的三种开发方式

    最近在学习QT GUI,单纯使用C++硬编码的方式,直接是采用QWidget部件来做,而不是采用QT Designer做UI界面,也不是采用QML+Javascript.单纯使用C++硬编码的方式,缺 ...