题意:

在二维平面的第一象限有\(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\)的过程注意取余,否则可能会溢出。

  1. #include <cstdio>
  2. #include <cstring>
  3. #include <algorithm>
  4. using namespace std;
  5. typedef long long LL;
  6. const int maxn = 100000 + 10;
  7. const int INF = 0x3f3f3f3f;
  8. const int maxnode = maxn << 5;
  9. struct Event
  10. {
  11. int pos, sum, type;
  12. bool operator < (const Event& t) const {
  13. return pos < t.pos || (pos == t.pos && type < t.type);
  14. }
  15. };
  16. struct Segment
  17. {
  18. int l, r, d;
  19. };
  20. Event events[maxn * 2];
  21. Segment a[maxn];
  22. int y[maxn], tot;
  23. int n, m, X;
  24. LL P;
  25. int sz;
  26. int cnt[maxnode], lch[maxnode], rch[maxnode];
  27. LL sum[maxnode];
  28. int root[maxn * 2];
  29. int update(int pre, int L, int R, int pos, LL val, int type) {
  30. int rt = ++sz;
  31. lch[rt] = lch[pre];
  32. rch[rt] = rch[pre];
  33. cnt[rt] = cnt[pre] + type;
  34. sum[rt] = sum[pre] + val;
  35. if(L < R) {
  36. int M = (L + R) / 2;
  37. if(pos <= M) lch[rt] = update(lch[pre], L, M, pos, val, type);
  38. else rch[rt] = update(rch[pre], M+1, R, pos, val, type);
  39. }
  40. return rt;
  41. }
  42. LL query(int rt, int L, int R, int k) {
  43. if(L == R) {
  44. if(cnt[rt] > k) return sum[rt] / cnt[rt] * k;
  45. else return sum[rt];
  46. }
  47. int M = (L + R) / 2;
  48. int num = cnt[lch[rt]];
  49. if(num >= k) return query(lch[rt], L, M, k);
  50. else return sum[lch[rt]] + query(rch[rt], M+1, R, k - num);
  51. }
  52. int main()
  53. {
  54. while(scanf("%d%d%d%lld", &n, &m, &X, &P) == 4) {
  55. for(int i = 0; i < n; i++) {
  56. scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].d);
  57. events[i * 2] = (Event){ a[i].l, a[i].d, 1 };
  58. events[i*2+1] = (Event){ a[i].r + 1, a[i].d, -1 };
  59. y[i] = a[i].d;
  60. }
  61. sort(events, events + n * 2);
  62. sort(y, y + n);
  63. tot = unique(y, y + n) - y;
  64. sz = 0;
  65. for(int i = 0; i < n * 2; i++) {
  66. Event& e = events[i];
  67. int pos = lower_bound(y, y + tot, e.sum) - y + 1;
  68. root[i + 1] = update(root[i], 1, tot, pos, e.sum * e.type, e.type);
  69. }
  70. LL pre = 1;
  71. while(m--) {
  72. int x; LL a, b, c;
  73. scanf("%d%lld%lld%lld", &x, &a, &b, &c);
  74. int K = (a * pre + b) % c;
  75. if(!K) { printf("0\n"); pre = 0; continue; }
  76. Event t;
  77. t = (Event){ x, 0, 2 };
  78. int rt = lower_bound(events, events + n * 2, t) - events;
  79. LL ans;
  80. if(K >= cnt[root[rt]]) ans = sum[root[rt]];
  81. else ans = query(root[rt], 1, tot, K);
  82. if(pre > P) ans <<= 1;
  83. pre = ans;
  84. printf("%lld\n", ans);
  85. }
  86. }
  87. return 0;
  88. }

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. zuul的本地跳转

  2. php设计模式-单例

    单例模式是一种常用的软件设计模式.在它的核心结构中只包含一个被称为单例的特殊类.通过单例模式可以保证系统中一个类只有一个实例. <设计模式>对此的定义:保证一个类仅有一个实例,并提供一个访 ...

  3. postgresql 存储过程动态插入数据 2

    最近学习postgresql,正一个小活要用上,所以就开始学习了!然而,学习的过程极其艰辛,但却也充满了乐趣. 一般来说数据库的操作不外如何增,删,改,查,而首要的就是要添加数据到数据库中,因为以前的 ...

  4. 整合mybatis分页插件及通用接口测试出现问题

    严重: Servlet.service() for servlet [springmvc] in context with path [/mavenprj] threw exception [Requ ...

  5. jquery笔记1--选择器

    一.概述:jQuery是一个快速.简洁的JavaScript框架,是继Prototype之后又一个优秀的JavaScript代码库(或JavaScript框架).jQuery设计的宗旨是“write ...

  6. DataSource--DBCP--C3P0--DBUtils

    一.DataSource 接口(javax.sql)     1.连接池:         由于与数据库连接的创建和销毁非常占用资源,因此提出了连接池技术,用于提升java程序操作数据库的性能;连接池 ...

  7. 使用as开发jni入门(附验证):配置ndk开发环境,配置as相关jni配置

    编写jni,生成so文件: 1.通过as内置的Android SDK下载需要使用的ndk,在系统环境变量设置相关参数 2.新建一个普通as项目,新建一个类,用来静态加载so库和书写本地native方法 ...

  8. sql优化实战:从1353秒到135秒(删除索引+修改数据+重建索引)

    最近在优化日结存储过程,日结存储过程中大概包含了20多个存储过程. 发现其有一个存储过程代码有问题,进一步发现结存的数据中有一个 日期字段business_date 是有问题的,这个字段对应的类型是v ...

  9. JavaScript_4_数据类型

    1. JavaScript对大小写敏感. 2. JavaScript是脚本语言.浏览器会在读取代码时,逐行地执行脚本代码.而对于传统编程来说,会在执行前对所有代码进行编译. 3. 变量什么用var, ...

  10. 如何对ABAP SE80 workbench做增强

    流程如下: 要获取更多Jerry的原创文章,请关注公众号"汪子熙":