HDU 4866 Shooting 扫描线 + 主席树
题意:
在二维平面的第一象限有\(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 扫描线 + 主席树的更多相关文章
- HDU 4866 Shooting (主席树)
题目链接 HDU 4866 题意 给定$n$条线段.每条线段平行$x$轴,离x轴的距离为$D$,覆盖的坐标范围为$[L, R]$. 现在有$m$次射击行动,每一次的射击行动可以描述为在横坐标$ ...
- HDU 4866 Shooting(主席树)题解
题意:在一个射击游戏里面,游戏者可以选择地面上[1,X]的一个点射击,并且可以在这个点垂直向上射击最近的K个目标,每个目标有一个价值,价值等于它到地面的距离.游戏中有N个目标,每个目标从L覆盖到R,距 ...
- HDU 4866 Shooting(持久化线段树)
view code//第二道持久化线段树,照着别人的代码慢慢敲,还是有点不理解 #include <iostream> #include <cstdio> #include & ...
- HDU 4866 Shooting 题解:主席树
这题的主要的坑点就是他给你的射击目标有重合的部分,如果你向这些重合的部分射击的话要考虑两种情况: 射击目标数量 ≥ 重合数量 : 全加上 射击目标数量 ≤ 重合数量 : 只加距离*射击目标数量 然而这 ...
- hdu 2665 Kth number 主席树
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Prob ...
- HDU 5919 Sequence II 主席树
Sequence II Problem Description Mr. Frog has an integer sequence of length n, which can be denoted ...
- 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 ...
- HDU - 2665 Kth number 主席树/可持久化权值线段树
题意 给一个数列,一些询问,问$[l,r]$中第$K$大的元素是哪一个 题解: 写法很多,主席树是最常用的一种之一 除此之外有:划分树,莫队分块,平衡树等 主席树的定义其实挺模糊, 一般认为就是可持久 ...
随机推荐
- Servlet 示例
引入jar包: servlet-api.jar ParameterServlet.java package com.mousewheel.springmvc; import java.io.IOExc ...
- JAVA基础之Properties类、序列化流及打印流、commons-IO
个人理解: Properties类是个存储String类型的键值对的集合类,可以用其存储一些关键的账号密码什么的,同时后面的注释可以很好的帮助理解,但是需要注意的是其文件中不能出现其他的符号:序列化与 ...
- tcp的三次连接握手和四次释放握手
http://blog.csdn.net/whuslei/article/details/6667471/ 这篇博客讲的很清楚. 下面我简单说明一下:三次连接握手,首先client发送请求报文,然后服 ...
- python3 socke 服务端与客户端实现(回炉)
#服务端#!/usr/bin/env python3 # -*- coding:utf-8 -*- from socket import * # 创建socket tcpSerSocket = soc ...
- SQLServer 2012 报表服务部署配置(2)
2.当系统打开"SQL Server安装中心",则说明我们可以开始正常的安装SQL Server 2012,可以通过"计划"."安装".&q ...
- python+selenium之断言Assertion
一.断言方法 断言是对自动化测试异常情况的判断. # -*- coding: utf-8 -*- from selenium import webdriver import unittest impo ...
- 如果不需要,建议移除net standard类库中的Microsoft.NETCore.Portable.Compatibility
使用Microsoft.NETCore.Portable.Compatibility会破坏该类库在Mono和Xamarin平台的兼容性 可能导致的问题 provides a compile-time ...
- Android(java)学习笔记126:判断SD卡状态和SD卡容量
1. 判断SD卡状态和SD卡存储空间大小 当我们在使用SD卡时候,如果我们想往SD卡里读写数据,我们必须在这之前进行一个逻辑判断,那就是判断SD卡状态和SD存储空间大小: 核心代码: String s ...
- [神经网络]一步一步使用Mobile-Net完成视觉识别(四)
1.环境配置 2.数据集获取 3.训练集获取 4.训练 5.调用测试训练结果 6.代码讲解 本文是第四篇,下载预训练模型并训练自己的数据集. 前面我们配置好了labelmap,下面我们开始下载训练好的 ...
- ListView适配器Adapter介绍与优化
一.ListView与Adapter的关系 ListView是Android开发过程中较为常见的组件之一,它将数据以列表的形式展现出来.一般而言,一个ListView由以下三个元素组成: 1.View ...