题意:

在二维平面的第一象限有\(n(1 \leq n \leq 10^5)\)条平行于\(x\)轴的线段,接下来有\(m\)次射击\(x \, a \, b \, c\)。

每次射击会获得一定的分数,假设上一轮的分数为\(pre\),那么这次射击就会在位置\(x\)处射击最近的\(K=(a \cdot pre + b) % c\)个靶子。

每射中一个靶子就会获得靶子到\(x\)轴距离的分数,如果上一轮分数\(pre > P\),那么本轮分数再乘\(2\)。

输出每次射击所得的分数。

分析:

首先从左到右扫描线段:

  • 遇到线段的左端点,在这个线的位置射穿过去的话,靶的个数增加\(1\),而且也会比原来得到对应的分数
  • 遇到线段的右端点,在这个线的位置射穿过去的话,靶的个数减少\(1\),而且也会比原来得到对应的分数

所以\(n\)条线段就有\(2n\)个事件,从左往右扫描,维护\(2n\)棵线段树,对应前\(i\)个事件发生后对应的靶子的个数以及到\(x\)轴距离之和。

然后每次计算出\(K\),接下来就是求树中前\(K\)小个数字之和,这是主席树的拿手本领。

在\(x\)处射击,要找到对应的那棵线段树,具体来说就是:

位置小于\(x\)的事件已经发生了,位置等于\(x\)的左端点事件也发生了,其他的事件都还没发生。

对于位置相同的事件,我们可以把左端点事件排序在右端点事件前面,这样就可以二分查找到对应的线段树。

最后在这棵线段树里查询答案。

\(Tips\):在计算\(K\)的过程注意取余,否则可能会溢出。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std; typedef long long LL;
const int maxn = 100000 + 10;
const int INF = 0x3f3f3f3f;
const int maxnode = maxn << 5; struct Event
{
int pos, sum, type;
bool operator < (const Event& t) const {
return pos < t.pos || (pos == t.pos && type < t.type);
}
}; struct Segment
{
int l, r, d;
}; Event events[maxn * 2];
Segment a[maxn];
int y[maxn], tot; int n, m, X;
LL P; int sz;
int cnt[maxnode], lch[maxnode], rch[maxnode];
LL sum[maxnode];
int root[maxn * 2]; int update(int pre, int L, int R, int pos, LL val, int type) {
int rt = ++sz;
lch[rt] = lch[pre];
rch[rt] = rch[pre];
cnt[rt] = cnt[pre] + type;
sum[rt] = sum[pre] + val;
if(L < R) {
int M = (L + R) / 2;
if(pos <= M) lch[rt] = update(lch[pre], L, M, pos, val, type);
else rch[rt] = update(rch[pre], M+1, R, pos, val, type);
}
return rt;
} LL query(int rt, int L, int R, int k) {
if(L == R) {
if(cnt[rt] > k) return sum[rt] / cnt[rt] * k;
else return sum[rt];
}
int M = (L + R) / 2;
int num = cnt[lch[rt]];
if(num >= k) return query(lch[rt], L, M, k);
else return sum[lch[rt]] + query(rch[rt], M+1, R, k - num);
} int main()
{
while(scanf("%d%d%d%lld", &n, &m, &X, &P) == 4) {
for(int i = 0; i < n; i++) {
scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].d);
events[i * 2] = (Event){ a[i].l, a[i].d, 1 };
events[i*2+1] = (Event){ a[i].r + 1, a[i].d, -1 };
y[i] = a[i].d;
}
sort(events, events + n * 2);
sort(y, y + n);
tot = unique(y, y + n) - y; sz = 0;
for(int i = 0; i < n * 2; i++) {
Event& e = events[i];
int pos = lower_bound(y, y + tot, e.sum) - y + 1;
root[i + 1] = update(root[i], 1, tot, pos, e.sum * e.type, e.type);
} LL pre = 1;
while(m--) {
int x; LL a, b, c;
scanf("%d%lld%lld%lld", &x, &a, &b, &c);
int K = (a * pre + b) % c;
if(!K) { printf("0\n"); pre = 0; continue; }
Event t;
t = (Event){ x, 0, 2 };
int rt = lower_bound(events, events + n * 2, t) - events;
LL ans;
if(K >= cnt[root[rt]]) ans = sum[root[rt]];
else ans = query(root[rt], 1, tot, K);
if(pre > P) ans <<= 1;
pre = ans;
printf("%lld\n", ans);
}
} return 0;
}

HDU 4866 Shooting 扫描线 + 主席树的更多相关文章

  1. HDU 4866 Shooting (主席树)

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

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

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

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

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

  4. HDU 4866 Shooting 题解:主席树

    这题的主要的坑点就是他给你的射击目标有重合的部分,如果你向这些重合的部分射击的话要考虑两种情况: 射击目标数量 ≥ 重合数量 : 全加上 射击目标数量 ≤ 重合数量 : 只加距离*射击目标数量 然而这 ...

  5. hdu 2665 Kth number 主席树

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

  6. HDU 5919 Sequence II 主席树

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

  7. HDU 4417 Super Mario 主席树

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

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

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

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

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

随机推荐

  1. WPF 模拟Button按钮事件触发

    this.Submit.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.Submit_Click)); //这种是无效的方法 thi ...

  2. Android 下的 SQLite 操作封装 —— DatabaseUtil

    看到别人写的代码不错,对自己目前的开发很有用,所以转载一下,希望也能帮助到其他人: 1.DatabaseUtil.java(封装的类) package com.dbexample; import an ...

  3. css经典布局之双飞翼

    经典的两个布局方式有圣杯布局和双飞翼布局,圣杯布局主要用在国外,双飞翼布局是淘宝的UED团队开发的,优化了圣杯布局.   主要解决页面分不同列显示的问题,   一般只做页面的时候,我们分三部分,左边, ...

  4. HDU 2256Problem of Precision(矩阵快速幂)

    题意 求$(\sqrt{2} + \sqrt{3})^{2n} \pmod {1024}$ $n \leqslant 10^9$ Sol 看到题解的第一感受:这玩意儿也能矩阵快速幂??? 是的,它能q ...

  5. H5的storage(sessionstorage&localStorage)简单存储删除

    众所周知,H5的storage有sessionstorage&localStorage,其中他们的共同特点是API相同 下面直接上代码,storage中的存储与删除: <!DOCTYPE ...

  6. ios 12 xcode10 新升级的编译报错libstdc++.6.0.9 Multiple commands produce

    问题一 编译报错 Showing Recent Messages :-1: Multiple commands produce '/Users/duning/Library/Developer/Xco ...

  7. ios 各种锁的使用性能比较

    iOS开发中常用的锁有如下几种 来比较一下遇到加锁的情况: 1. @synchronized 关键字加锁 2. NSLock 对象锁 3. NSCondition  4. NSConditionLoc ...

  8. 挂sqlserver计划,系统自动分配拣货任务

    USE [P2WMS_WH43] GO /****** Object: StoredProcedure [dbo].[sp_fru_CalcAllocatePickData] Script Date: ...

  9. 洛谷 P1903 【模板】分块/带修改莫队(数颜色)

    题目描述 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会像你发布如下指令: 1. Q L R代表询问你从第L支画笔到第R支画笔中共有几种不同颜色的画笔. 2 ...

  10. 【exFat】利用命令提示符在windows 7 及 windows server 2008 r2 中将卷(分区)格式化为exFAT

    步骤 运行cmd.exe: 查看磁盘信息.输入diskpart并回车: 选择磁盘.输入select disk 0(“0”代表要选择的磁盘号)并回车: 查看所选硬盘的分区.输入list partitio ...