P3168 [CQOI2015]任务查询系统

题目描述

最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。

超级计算机中的任务用三元组\((S_i,E_i,P_i)\)描述,\((S_i,E_i,P_i)\)表示任务从第\(S_i\)秒开始,在第\(E_i\)秒后结束(第\(S_i\)秒和\(E_i\)秒任务也在运行),其优先级为\(P_i\)。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。

调度系统会经常向查询系统询问,第\(X_i\)秒正在运行的任务中,优先级最小的\(K_i\)个任务(即将任务按照优先级从小到大排序后取前\(K_i\)个)的优先级之和是多少。

特别的,如果\(K_i\)大于第\(X_i\)秒正在运行的任务总数,则直接回答第\(X_i\)秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在\(1\)到\(n\)之间(包含\(1\)和\(n\))。

输入输出格式

输入格式:

输入文件第一行包含两个空格分开的正整数\(m\)和\(n\),分别表示任务总数和时间范围。

接下来m行,每行包含三个空格分开的正整数\(S_i\)、\(E_i\)和\(P_i(S_i<=E_i)\),描述一个任务。接下来\(n\)行,每行包含四个空格分开的整数\(X_i\)、\(A_i\)、\(B_i\)和\(C_i\),描述一次查询。

查询的参数\(K_i\)需要由公式 \(K_i=1+(A_i*Pre+B_i) \ mod \ C_i\)计算得到。其中\(Pre\)表示上一次查询的结果,对于第一次查询,\(Pre=1\)。

输出格式:

输出共\(n\)行,每行一个整数,表示查询结果。

说明

对于100%的数据,\(1<=m,n,S_i,E_i,C_i<=100000\),\(0<=A_i,B_i<=100000\),\(1<=P_i<=10000000\),\(X_i\)为\(1\)到\(n\)的一个排列

时空范围:2sec,256mb


化简模型,给出\(m\)个三元组\((s,e,p)\)

询问\((x,k)\)为满足\(s \le x \le e\)的三元组的前\(k\)大\(p\)值之和,强制在线

一看是一个偏序类题目,我们可以多维数据结构暴力嵌套,这个题最多允许\(log^2\),又有第\(k\)大询问,自然的想到主席树降维

使用树状树状套主席树求解

其中树状树状的区间代表从大到小排序的\(E_i\)

树状树状的每个区间放对应的一群线段树,我们先对区间按\(S_i\)从小到大排序,然后按这个顺序建主席树就行了

主席树的节点存离散(不离散似乎也过了)的\(p_i\)值,注意维护一下区间和

查询的时候,在每个树状数组对应的主席树上一起二分即可,注意重复的元素

Code

  1. #include <cstdio>
  2. #include <algorithm>
  3. #include <vector>
  4. #define ll long long
  5. using namespace std;
  6. const int N=1e5+10;
  7. struct node
  8. {
  9. int s,t,p;
  10. bool friend operator <(node n1,node n2){return n1.t>n2.t;}
  11. }rask[N];
  12. struct RT
  13. {
  14. int s,now;
  15. RT(){}
  16. RT(int s,int now){this->s=s,this->now=now;}
  17. bool friend operator <(RT n1,RT n2){return n1.s<n2.s;}
  18. }rt;
  19. vector <RT> root[N];
  20. int cnt[N*244],ch[N*244][2],tot,n,m,mxx;ll sum[N*244];
  21. int max(int x,int y){return x>y?x:y;}
  22. #define ls ch[now][0]
  23. #define rs ch[now][1]
  24. #define ols ch[las][0]
  25. #define ors ch[las][1]
  26. void update(int now)
  27. {
  28. sum[now]=sum[ls]+sum[rs];
  29. cnt[now]=cnt[ls]+cnt[rs];
  30. }
  31. int build(int las,int l,int r,int pos)
  32. {
  33. int now=++tot;
  34. if(l==r)
  35. {
  36. cnt[now]=cnt[las]+1;
  37. sum[now]=1ll*cnt[now]*l;
  38. return now;
  39. }
  40. int mid=l+r>>1;
  41. if(pos<=mid)
  42. {
  43. ls=build(ols,l,mid,pos);
  44. rs=ors;
  45. }
  46. else
  47. {
  48. ls=ols;
  49. rs=build(ors,mid+1,r,pos);
  50. }
  51. update(now);
  52. return now;
  53. }
  54. void init()
  55. {
  56. scanf("%d%d",&m,&n);
  57. for(int i=1;i<=m;i++)
  58. scanf("%d%d%d",&rask[i].s,&rask[i].t,&rask[i].p),mxx=max(mxx,rask[i].p);
  59. sort(rask+1,rask+1+m);
  60. for(int i=1;i<=m;i++)
  61. {
  62. for(int j=i-(i&-i)+1;j<=i;j++)
  63. {
  64. rt=RT(rask[j].s,j);
  65. root[i].push_back(rt);
  66. }
  67. sort(root[i].begin(),root[i].end());
  68. for(int las=0,j=0;j<root[i].size();j++)
  69. las=root[i][j].now=build(las,1,mxx,rask[root[i][j].now].p);
  70. }
  71. }
  72. ll query(int x,int pos,int k)//时间,前pos可查,第k值
  73. {
  74. int now[50],p=0;
  75. for(int i=pos;i;i-=i&-i)
  76. {
  77. RT t=RT(x,0);
  78. int j=upper_bound(root[i].begin(),root[i].end(),t)-root[i].begin()-1;
  79. now[++p]=root[i][j].now;
  80. }
  81. int l=1,r=mxx;ll ans=0;
  82. while(l<r)
  83. {
  84. int mid=l+r>>1,s=0;
  85. for(int i=1;i<=p;i++) s+=cnt[ch[now[i]][0]];
  86. if(s>=k)
  87. {
  88. for(int i=1;i<=p;i++) now[i]=ch[now[i]][0];
  89. r=mid;
  90. }
  91. else
  92. {
  93. for(int i=1;i<=p;i++) ans+=sum[ch[now[i]][0]],now[i]=ch[now[i]][1];
  94. l=mid+1,k-=s;
  95. }
  96. }
  97. int cnt0=0;
  98. for(int i=1;i<=p;i++) cnt0+=cnt[now[i]];
  99. ans+=1ll*l*min(cnt0,k);
  100. return ans;
  101. }
  102. void work()
  103. {
  104. ll pre=1;
  105. for(int pos,x,a,b,c,k,i=1;i<=n;i++)
  106. {
  107. scanf("%d%d%d%d",&x,&a,&b,&c);
  108. k=(a*(int)(pre%(1ll*c))+b)%c+1;
  109. node t={0,x,0};
  110. pos=upper_bound(rask+1,rask+1+m,t)-rask-1;
  111. printf("%lld\n",pre=query(x,pos,k));
  112. }
  113. }
  114. int main()
  115. {
  116. init(),work();
  117. return 0;
  118. }

然而,我们注意到这个问题有这样一个暴力

对操作,我们可以把每个对应位置上都加上这个优先级,并用权值线段树维护

然后查询时,直接进入对应位置的权值线段树查询即可

而事实上,我们发现这是对每个位置有一个区间加,我们可以采用差分数组的思想

把三元组\((s,e,p)\)的\(s\)位置的\(p\)值\(+1\),把\(e+1\)位置\(p\)值\(-1\)(这里\(p\)值在对于位置的权值线段树上)

然后我们查询的时候,就求这些权值线段树的前缀和就可以了

这不就是主席树干的事情吗

于是乎问题就可以直接用主席树做了

Code:

  1. #include <cstdio>
  2. #include <algorithm>
  3. #define ll long long
  4. using namespace std;
  5. const int N=1e5+10;
  6. struct node{int s,e,p;}rask[N];
  7. int a[N];
  8. int cnt[N*100],ch[N*100][2],root[N],tot,n,m,num;ll sum[N*100];
  9. #define ls ch[now][0]
  10. #define rs ch[now][1]
  11. void updata(int now)
  12. {
  13. sum[now]=sum[ls]+sum[rs];
  14. cnt[now]=cnt[ls]+cnt[rs];
  15. }
  16. void build(int &now,int l,int r,int pos,int del)
  17. {
  18. if(!now) now=++tot;
  19. if(l==r)
  20. {
  21. cnt[now]+=del;
  22. sum[now]=1ll*cnt[now]*a[l];
  23. return;
  24. }
  25. int mid=l+r>>1;
  26. if(pos<=mid)
  27. build(ls,l,mid,pos,del);
  28. else
  29. build(rs,mid+1,r,pos,del);
  30. updata(now);
  31. }
  32. int rebuild(int x,int y)
  33. {
  34. if(!x||!y) return x+y;
  35. int now=++tot;
  36. sum[now]=sum[x]+sum[y];
  37. cnt[now]=cnt[x]+cnt[y];
  38. ls=rebuild(ch[x][0],ch[y][0]);
  39. rs=rebuild(ch[x][1],ch[y][1]);
  40. return now;
  41. }
  42. void init()
  43. {
  44. scanf("%d%d",&m,&n);
  45. for(int i=1;i<=m;i++)
  46. {
  47. scanf("%d%d%d",&rask[i].s,&rask[i].e,&rask[i].p);
  48. a[i]=rask[i].p;
  49. }
  50. sort(a+1,a+1+m);
  51. ++n;
  52. num=unique(a+1,a+1+m)-a-1;
  53. for(int i=1;i<=m;i++)
  54. {
  55. rask[i].p=lower_bound(a+1,a+1+num,rask[i].p)-a;
  56. build(root[rask[i].s],1,num,rask[i].p,1);
  57. build(root[rask[i].e+1],1,num,rask[i].p,-1);
  58. }
  59. for(int i=1;i<=n;i++)
  60. root[i]=rebuild(root[i-1],root[i]);
  61. }
  62. ll query(int now,int l,int r,int k)
  63. {
  64. if(l==r)
  65. return 1ll*a[l]*min(k,cnt[now]);
  66. int mid=l+r>>1;
  67. if(cnt[ls]>=k) return query(ls,l,mid,k);
  68. else return sum[ls]+query(rs,mid+1,r,k-cnt[ls]);
  69. }
  70. void work()
  71. {
  72. ll pre=1;
  73. for(int x,a,b,c,k,i=1;i<n;i++)
  74. {
  75. scanf("%d%d%d%d",&x,&a,&b,&c);
  76. k=(a*(int)(pre%(1ll*c))+b)%c+1;
  77. printf("%lld\n",pre=query(root[x],1,num,k));
  78. }
  79. }
  80. int main()
  81. {
  82. init(),work();
  83. return 0;
  84. }

2018.9.13

洛谷 P3168 [CQOI2015]任务查询系统 解题报告的更多相关文章

  1. 洛谷P3168 [CQOI2015]任务查询系统 [主席树,差分]

    题目传送门 任务查询系统 题目描述 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任 ...

  2. ●洛谷P3168 [CQOI2015]任务查询系统

    题链: https://www.luogu.org/problemnew/show/P3168题解: 主席树 强制在线? 那就直接对每一个前缀时间建一个线段树(可持久化线段树),线段树维护优先度权值. ...

  3. 洛谷P3168 [CQOI2015]任务查询系统

    #include<cstdio> #include<cstdlib> #include<algorithm> #include<cstring> #in ...

  4. 洛谷 P3171 [CQOI2015]网络吞吐量 解题报告

    P3171 [CQOI2015]网络吞吐量 题目描述 路由是指通过计算机网络把信息从源地址传输到目的地址的活动,也是计算机网络设计中的重点和难点.网络中实现路由转发的硬件设备称为路由器.为了使数据包最 ...

  5. P3168 [CQOI2015]任务查询系统

    题目地址:P3168 [CQOI2015]任务查询系统 主席树的模板题 更模板的在这儿:P3834 [模板]可持久化线段树 1(主席树) 形象的说,P3834是"单点修改,区间查询" ...

  6. bzoj3932 / P3168 [CQOI2015]任务查询系统(主席树+差分)

    P3168 [CQOI2015]任务查询系统 看到第k小,就是主席树辣 对于每一段任务(a,b,k),在版本a的主席树+k,版本b+1的主席树-k 同一时间可能有多次修改,所以开个vector存操作, ...

  7. 洛谷_Cx的故事_解题报告_第四题70

    1.并查集求最小生成树 Code: #include <stdio.h> #include <stdlib.h>   struct node {     long x,y,c; ...

  8. 洛谷$P$3168 任务查询系统 $[CQOI2015]$ 主席树

    正解:主席树 解题报告: 传送门! 首先考虑如果是单点修改,那就是个线段树板子嘛$QwQ$ 然后现在是区间修改,对于区间修改,显然就考虑差分下,就变成单点修改辣$QwQ$ 同时单点查询前$k$小也就变 ...

  9. 洛谷 P2317 [HNOI2005]星际贸易 解题报告

    P2317 [HNOI2005]星际贸易 题目描述 输入输出格式 输入格式: 输出格式: 如果可以找到这样的方案,那么输出文件output.txt中包含两个整数X和Y.X表示贸易额,Y表示净利润并且两 ...

随机推荐

  1. 爬虫学习(十一)——bs4基础学习

    ba4的介绍: bs4是第三方提供的库,可以将网页生成一个对象,这个网页对象有一些函数和属性,可以快捷的获取网页中的内容和标签 lxml的介绍 lxml是一个文件的解释器,python自带的解释器是: ...

  2. Java反射+注解案例

    注解类代码,注解的属性可以有多个: package reflect; import java.lang.annotation.Retention; import java.lang.annotatio ...

  3. springBoot支持PageHelp插件使用学习笔记

    首先在springboot项目的maven中加入依赖(版本可能需要自己选择合适的) <dependency> <groupId>com.github.pagehelper< ...

  4. .Net Core爬虫爬取妹子网图片

    现在网上大把的Python的爬虫教程,很少看见有用C#写的,正好新出的.Net Core可以很方便的部署到Linux上,就用妹子图做示范写个小爬虫 在C#下有个很方便的类库 HtmlAgilityPa ...

  5. 交换机基础配置之跨交换机划分vlan

    我们以上面的拓扑图来进行实验 四台pc机都在同一网段 pc1和pc2在同一台交换机上 pc3和pc4在同一台交换机上 现在我们实验的目的就是将pc1和pc3划分到同一vlan pc2和pc4划分到同一 ...

  6. laravel cache get 是如何调用的?

    本文使用版本为laravel5.5 cache get public function cache() { $c=\Cache::get('app'); if(!$c) { \Cache::put(' ...

  7. python__高级 : GC垃圾回收相关

    python的垃圾回收机制是以引用计数为主,加上标记-清除,分代收集等辅助方式组成的,如果想打开gc功能,需要 import gc 模块 ,然后 gc.enable() 就打开了这个功能,关闭是 gc ...

  8. JS常用数组方法及实例

    1.join(separator):将数组的元素组起一个字符串,以separator为分隔符 ,,,,]; var b = a.join("|"); //如果不用分隔符,默认逗号隔 ...

  9. 006---Django静态文件配置

    静态文件:Js.Css.Fonts.Image等 这个不难.在setting.py文件加一行 # 别名 用户在url地址栏输入127.0.0.1:8000/static/文件 可以直接访问static ...

  10. PHP.TP框架下商品项目的优化4-优化商品添加表单js

    优化商品添加表单js 思路 1.制作五个按钮 2.下面五个table 3.全部隐藏,点击则显示 4.点击第几个按钮就显示第几个table 具体操作 1.添加按钮 2.添加五个table并添加class ...