传送门

看到这个题有个很暴力的想法,

可以每一个时间点都建一颗主席树,主席树上叶子节点 i 表示优先级为 i 的任务有多少个。

当 x 到 y 有个优先级为 k 的任务时,循环 x 到 y 的每个点,都插入一个 k。

当然这样肯定完蛋。

x 到 y 插入一个优先级为 k 的任务?

想到差分,给时间点为 x 的主席树插入 k,给时间点为 y + 1 的主席树插入 -k。

那么求一个树状数组的前缀和就好了。

前缀和?

用树状数组优化。

这样就可以用 树状数组 套 主席树 来做。

——代码

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #define LL long long
  5.  
  6. const int MAXN = 1e5 + , p = ;
  7. int n, m, cnt, t;
  8. int S[MAXN], E[MAXN], P[MAXN], num[MAXN], root[MAXN], id[MAXN], q[], s[MAXN * p], ls[MAXN * p], rs[MAXN * p];
  9. LL sum[MAXN * p], pre = ;
  10.  
  11. inline int read()
  12. {
  13. int x = , f = ;
  14. char ch = getchar();
  15. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
  16. for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
  17. return x * f;
  18. }
  19.  
  20. inline bool cmp(int x, int y)
  21. {
  22. return P[x] < P[y];
  23. }
  24.  
  25. inline void insert(int last, int &now, int l, int r, int x, int v1, int v2)
  26. {
  27. if(!now) now = ++cnt;
  28. sum[now] = sum[last] + v1, s[now] = s[last] + v2, ls[now] = ls[last], rs[now] = rs[last];
  29. if(l == r) return;
  30. int mid = (l + r) >> ;
  31. if(x <= mid) insert(ls[last], ls[now], l, mid, x, v1, v2);
  32. else insert(rs[last], rs[now], mid + , r, x, v1, v2);
  33. }
  34.  
  35. inline LL query(int l, int r, int k)
  36. {
  37. if(l == r)
  38. {
  39. LL t2 = ;
  40. for(int i = ; i <= t; i++) t2 += sum[q[i]];
  41. return t2;
  42. }
  43. LL t2 = ;
  44. int t1 = , mid = (l + r) >> ;
  45. for(int i = ; i <= t; i++) t1 += s[ls[q[i]]], t2 += sum[ls[q[i]]];
  46. if(k <= t1)
  47. {
  48. for(int i = ; i <= t; i++) q[i] = ls[q[i]];
  49. return query(l, mid, k);
  50. }
  51. else
  52. {
  53. for(int i = ; i <= t; i++) q[i] = rs[q[i]];
  54. return t2 + query(mid + , r, k - t1);
  55. }
  56. }
  57.  
  58. int main()
  59. {
  60. int i, j, x, a, b, c;
  61. LL k;
  62. n = read();
  63. m = read();
  64. for(i = ; i <= n; i++)
  65. {
  66. S[i] = read();
  67. E[i] = read();
  68. P[i] = read();
  69. id[i] = i;
  70. }
  71. std::sort(id + , id + n + , cmp);
  72. for(i = ; i <= n; i++) num[id[i]] = i;
  73. for(i = ; i <= n; i++)
  74. {
  75. for(j = S[i]; j <= n; j += j & -j) insert(root[j], root[j], , n, num[i], P[i], );
  76. for(j = E[i] + ; j <= n; j += j & -j) insert(root[j], root[j], , n, num[i], -P[i], -);
  77. }
  78. for(i = ; i <= m; i++)
  79. {
  80. scanf("%d %d %d %d", &x, &a, &b, &c);
  81. k = + (LL)(a * pre + b) % c;
  82. t = ;
  83. for(j = x; j; j -= j & -j) q[++t] = root[j];
  84. pre = query(, n, k);
  85. printf("%lld\n", pre);
  86. }
  87. return ;
  88. }

其实如果按照时间排序的话,依次插入主席树,就可以维护前缀和,而省去了树状数组的麻烦。

然后注意的是每个时间点有可能会有多颗主席树。

——代码

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <algorithm>
  4. #define LL long long
  5.  
  6. const int MAXN = 1e5 + ;
  7. int n, m, tot, size, cnt;
  8. int num[MAXN], id[MAXN], v[MAXN], ls[MAXN * ], rs[MAXN * ], s[MAXN * ], root[MAXN];
  9. LL pre = , sum[MAXN * ];
  10. struct node
  11. {
  12. int S, val, type, num;
  13. }p[MAXN * ];
  14.  
  15. inline int read()
  16. {
  17. int x = , f = ;
  18. char ch = getchar();
  19. for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -;
  20. for(; isdigit(ch); ch = getchar()) x = (x << ) + (x << ) + ch - '';
  21. return x * f;
  22. }
  23.  
  24. inline bool cmp(node x, node y)
  25. {
  26. return x.S < y.S;
  27. }
  28.  
  29. inline void insert(int &now, int l, int r, int x, int v1, int v2)
  30. {
  31. ++cnt;
  32. sum[cnt] = sum[now] + v1;
  33. s[cnt] = s[now] + v2;
  34. ls[cnt] = ls[now];
  35. rs[cnt] = rs[now];
  36. now = cnt;
  37. if(l == r) return;
  38. int mid = (l + r) >> ;
  39. if(x <= mid) insert(ls[now], l, mid, x, v1, v2);
  40. else insert(rs[now], mid + , r, x, v1, v2);
  41. }
  42.  
  43. inline LL query(int now, int l, int r, int x)
  44. {
  45. if(l == r) return sum[now];
  46. int mid = (l + r) >> ;
  47. if(x <= s[ls[now]]) return query(ls[now], l, mid, x);
  48. else return sum[ls[now]] + query(rs[now], mid + , r, x - s[ls[now]]);
  49. }
  50.  
  51. inline bool cmp1(int x, int y)
  52. {
  53. return v[x] < v[y];
  54. }
  55.  
  56. int main()
  57. {
  58. int i, j, x, y, z, a;
  59. LL k;
  60. n = read();
  61. m = read();
  62. for(i = ; i <= n; i++)
  63. {
  64. x = read();
  65. y = read();
  66. v[i] = read();
  67. num[i] = i;
  68. p[++tot].S = x, p[tot].val = v[i], p[tot].type = ;
  69. p[++tot].S = y + , p[tot].val = -v[i], p[tot].type = -;
  70. }
  71. std::sort(num + , num + n + , cmp1);
  72. for(i = ; i <= n; i++) id[num[i]] = i;
  73. /*std::sort(v + 1, v + n + 1);
  74. size = std::unique(v + 1, v + n + 1) - (v + 1);
  75. for(i = 1; i <= n; i++) id[i] = std::lower_bound(v + 1, v + size + 1, id[i]) - v;*/
  76. tot = ;
  77. for(i = ; i <= n; i++) p[++tot].num = id[i], p[++tot].num = id[i];
  78. std::sort(p + , p + tot + , cmp);
  79. j = ;
  80. for(i = ; i <= m; i++)
  81. {
  82. root[i] = root[i - ];
  83. while(p[j].S == i)
  84. insert(root[i], , n, p[j].num, p[j].val, p[j].type), j++;
  85. }
  86. for(i = ; i <= m; i++)
  87. {
  88. a = read();
  89. x = read();
  90. y = read();
  91. z = read();
  92. k = + (LL)(x * pre + y) % z;
  93. printf("%lld\n", pre = query(root[a], , n, k));
  94. }
  95. return ;
  96. }

最后,需要注意对动态开点的理解。

以及,这个题是对优先级离散化,优先级有可能有相同的,但是离散化却不去重,这就会使得相同数值会是递增的一段数。

为什么不去重?

这是为了方便找前 k 个。

如果去重,有可能 query 时,找到一个叶子节点它的个数会超过一个,比如说 5 个,而只要找 3 个,那样处理就比较麻烦,还得再记录每个叶子节点的优先级。

不去重就保证了每个叶节点的个数只有一个,而对于答案没有影响。

[BZOJ3932] [CQOI2015]任务查询系统(主席树 || 树状数组 套 主席树 + 差分 + 离散化)的更多相关文章

  1. BZOJ3932 CQOI2015 任务查询系统 【主席树】

    BZOJ3932 CQOI2015 任务查询系统 Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的任务用三元组(Si,Ei, ...

  2. [COGS257]动态排名系统 树状数组套主席树

    257. 动态排名系统 时间限制:5 s   内存限制:512 MB [问题描述]给定一个长度为N的已知序列A[i](1<=i<=N),要求维护这个序列,能够支持以下两种操作:1.查询A[ ...

  3. bzoj1901--树状数组套主席树

    树状数组套主席树模板题... 题目大意: 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[ ...

  4. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  5. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  6. BZOJ1901 - Dynamic Rankings(树状数组套主席树)

    题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t  要求你把第i个数修改为t 题解 动态的区间第k ...

  7. BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树

    BZOJ_3196_Tyvj 1730 二逼平衡树_树状数组套主席树 Description 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作: 1.查询k在区间内的排 ...

  8. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  9. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

随机推荐

  1. HBase Region Assign流程详解

    Hbase是kv存储,但是逻辑上我们可以把存储在hbase上的kv数据当成表,rowkey可以认为是表的主键.为了便于分布式操作,hbase会把表横向切分成一块一块的数据,而每块就是一个Region. ...

  2. echart分组柱形图绑定数据

    <!DOCTYPE html> <head> <meta charset="utf-8"> <title>ECharts </ ...

  3. 源代码管理git的使用

    Git ----本地仓库---- 1.新建一个“本地仓库” git init 2.配置仓库 ①告诉git你是谁 git config user.name syl ②告诉git怎么联系你 git con ...

  4. webpack3整理(第二节/满三节)

    消除未使用的CSS:安装PurifyCSS-webpack插件 cnpm i purifycss-webpack purify-css -D const glob = require('glob'); ...

  5. 核武器代理CC工具V3.42最新版本!

    软件说明 !!!有新版本更新,请移步到更新地址:https://www.cnblogs.com/cnhacker/p/10878688.html ########################### ...

  6. CAD参数绘制填充(com接口)

    填充是CAD图纸中不可或缺的对象,在机械设计行业,常常需要将零部件剖开,以表现其内部的细节,而这些被剖开的截面会用填充来表示:在工程设计行业,一些特殊的材料或地形,也会用填充来表示. C#中实现代码说 ...

  7. numpy调试

    x1 = np.arange(9.0) 结果就是: array([ 0., 1., 2., 3., 4., 5., 6., 7., 8.]) 拿这个来初始化进行调试

  8. Linux C下变量和常量的存储的本质

    源代码 #cat main.c #include <stdio.h> int i = 100; int main(void) { func(); return 0; } #cat func ...

  9. Android之多种Bitmap效果(4)

    1. 将图片变为圆角 2. 获取缩略图图片 3. LOMO特效 4. 旧时光特效 5. 暖意特效 6. 根据饱和度.色相.亮度调整图片 7. 添加图片外边框 8. 添加内边框 9. 创建一个缩放的图片 ...

  10. oracle分析函数之ratio_to_report

    ratio_to_report主要完成对百分比的计算,语法为ratio_to_report(exp) over()也就是根据over窗口函数的作用区间,求出作用区间中的单个值在整个区间的总值的比重比如 ...