【主席树】BZOJ3932-[CQOI2015]任务查询系统

【题目大意】

超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。

【思路】

主席树。在Si秒开始,在Ei秒结束,相当于在Si秒加一,在Ei秒减一的前缀和。

把优先级看作数值,把时间看作T树下标。将优先级离散化后,按照时间排序,记录三元组(time,p,delta),描述时间,优先级及变化量(+1或-1),对于同一个时间,如果当前时间第一次出现,在T[time-1]的基础上更新,否则在T[time]的基础上更新。注意,中间空白的时间段,T[time]=T[time-1]。

【错误点】

query返回条件,但l==r时,不可以直接返回sum,而是sum/size*k。

因为我当前的size可能大于k。

  1 //时刻->下标
  2 //优先级->数值
  3 #include<iostream>
  4 #include<cstdio>
  5 #include<cstring>
  6 #include<algorithm>
  7 #include<vector>
  8 #define lson l,m
  9 #define rson m+1,r
 10 using namespace std;
 11 const int MAXN=100000+50;
 12 typedef long long ll;
 13 struct node
 14 {
 15     int time,p,delta;
 16
 17 }a[MAXN*2];
 18 bool cmp(node x,node y)
 19 {
 20     return (x.time<y.time);
 21 }
 22 int m,n,tot,d;
 23 int hash[MAXN],T[MAXN],size[MAXN<<7],L[MAXN<<7],R[MAXN<<7];
 24 ll sum[MAXN<<7];
 25
 26 int build(int l,int r)
 27 {
 28     int rt=++tot;
 29     sum[rt]=size[rt]=0;
 30     if (l<r)
 31     {
 32         int m=(l+r)>>1;
 33         L[rt]=build(lson);
 34         R[rt]=build(rson);
 35     }
 36     return rt;
 37 }
 38
 39 int update(int pre,int l,int r,int x,int delta)
 40 {
 41     int rt=++tot;
 42     L[rt]=L[pre],R[rt]=R[pre];
 43     sum[rt]=sum[pre]+(ll)delta*hash[x]; // sum  优先级的和:例如两个优先级为3的人物,那么sum=6,而size=2
 44     size[rt]=size[pre]+delta;            // size 优先级个数的和:例如两个优先级为3的人物,那么sum=6,而size=2
 45     if (l!=r)
 46     {
 47         int m=(l+r)>>1;
 48         if (x<=m) L[rt]=update(L[rt],lson,x,delta);
 49             else R[rt]=update(R[rt],rson,x,delta);
 50     }
 51     return rt;
 52 }
 53
 54
 55 ll query(int rt,int l,int r,ll k)
 56 {
 57     int nowsize=size[rt];
 58     if (k>=nowsize) return (sum[rt]);
 59     if (l==r) return (sum[rt]/size[rt]*k);
 60     //当l==r时,当前值可能有多个,且总数大于k,所以只需返回k*当前值即可
 61     int num=size[L[rt]];
 62     ll ret;
 63     int m=(l+r)>>1;
 64     if(num>=k)
 65         ret=query(L[rt], lson, k);
 66     else
 67         ret=sum[L[rt]]+query(R[rt],rson, k-num);
 68     return ret;
 69 }
 70
 71 void init()
 72 {
 73     tot=0;
 74     scanf("%d%d",&m,&n);
 75     for (int i=1;i<=m;i++)
 76     {
 77         int s,e,p;
 78         scanf("%d%d%d",&s,&e,&p);
 79         a[2*i-1]=(node){s,p,1};
 80         a[2*i]=(node){e+1,p,-1};
 81         hash[i]=p;
 82     }
 83     sort(hash+1,hash+m+1);
 84     m=m*2;
 85     sort(a+1,a+m+1,cmp);
 86
 87     d=unique(hash+1,hash+(m>>1)+1)-(hash+1);
 88     T[0]=build(1,d);
 89     for (int i=1;i<=m;i++)
 90     {
 91         int x=lower_bound(hash+1,hash+d+1,a[i].p)-hash;
 92         int t=a[i].time;
 93         if (i==1 || t!=a[i-1].time)
 94         {
 95             if (i!=1) for (int j=a[i-1].time+1;j<t;j++) T[j]=T[j-1];
 96             T[t]=update(T[t-1],1,d,x,a[i].delta);
 97         }
 98         else T[t]=update(T[t],1,d,x,a[i].delta);
 99     }
100 }
101
102 void solve()
103 {
104     int pre=1;
105     for (int i=0;i<n;i++)
106     {
107         ll x,a,b,c;
108         scanf("%lld%lld%lld%lld",&x,&a,&b,&c);
109         ll k=1+(ll)(a*pre+b)%c;
110         ll ans=query(T[x],1,d,k);
111         printf("%lld\n",ans);
112         pre=ans;
113     }
114 }
115
116 int main()
117 {
118     //freopen("cqoi15_query.in","r",stdin);
119     //freopen("cqoi15_query.out","w",stdout);
120     init();
121     solve();
122     return 0;
123 } 
时间: 2024-12-08 12:38:05

【主席树】BZOJ3932-[CQOI2015]任务查询系统的相关文章

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

[bzoj3932][CQOI2015][任务查询系统] (主席树)

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

bzoj3932 [CQOI2015]任务查询系统——主席树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3932 第二道主席树!本来想自己手胡一下,但是还是写不下去了... 参考博客:https://www.cnblogs.com/CQzhangyu/p/6295579.html 就是对每个时间节点建一棵权值线段树,节点太多所以开成主席树: WA了好久,竟然是错在二分的地方了???看了半天还是不知道为什么错,那个写法已经用了好久了啊... 代码如下: #include<iostream> #i

BZOJ3932: [CQOI2015]任务查询系统

传送门 真不知道我没学主席树之前是有什么勇气说自己高级数据结构以及学的七七八八了. 这道题应该也是算是主席树的经典运用. 刚开始脑抽了,想把(S,E,P)的处理直接在线用树状数组xjb搞搞算了.写完后才意识到树状数组无法(很难?)实现区间修改. 然后想了想既然这个是一下子把所有修改都放上了直接用树状数组差分一下不就好了! 然后又深感自己制杖,为什么要用树状数组差分呢,直接开几个vector维护一下就行了. 说是修改,本质上是不带修改的主席树,很快搞完.WA,眼查,无果,跟踪,无果. 拍了几组小数

3932: [CQOI2015]任务查询系统

3932: [CQOI2015]任务查询系统 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2559  Solved: 819[Submit][Status][Discuss] Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为P

【BZOJ3932】任务查询系统,主席树与差分的建树思想

Time:2016.05.08 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 说真的我一开始做这个题真不知道怎么建树,只知道应该以时间为根建树,记录优先值并维护前缀和,但想不出怎么用到主席树的前缀建树思想,暴力建树+修改肯定是不科学的-- 后来去看题解,发现又是差分. 回想起被运输计划支配的恐惧--(还是自己太弱的缘故) 不过这个差分比较简单,因为它正好利用了第i棵主席树以第i-1棵树为基础建树的思路,比如某一任务的时间区间为[l,r],优先度为p,那么我们在root[l]上

BZOJ 3932: [CQOI2015]任务查询系统 | 主席树练习题

题目: 洛谷也能评测 题解: De了好长时间BUG发现是自己sort前面有一行for没删,气死. 题目询问第x秒时候前k小的P值之和. 朴素想法: 我们可以把P值离散化,然后对于每个时刻建一棵定义域是离散化后P值的线段树 每个节点维护了这个节点代表区间的任务个数和这些任务离散化之前的P值之和, 对于每个在这个时间段的任务,插入,即在p位置单点修改 询问就是类似二叉查找树的写法 高级想法: 首先把一段任务拆成两个:添加和删除,用三元组(t,p,d)表示,d=1表示插入,d=-1表示删除 对于第ma

P3168 [CQOI2015]任务查询系统 主席树 差分数组

现在有一群任务,每个任务都有开始和结束的时间和一个优先级,给你所有任务的开始结束时间和优先级,问你在某个时间点优先级最小的k个的优先级的和是多少. 普通的主席树是单点修改 区间查询   这题正好相反 可以用差分数组来做  区间查询改为1-i的前缀和 注意copy结点的方式 不能简单的复制T  还有son  t num 重复累加的操作  要写成T[i] T[i]      而不是  T[i-1] T[i] 主席树的范围只和放入的数据的离散化下标有关   和历史版本号没有任何关系 这题的时间为历史版

【bzoj3932】 CQOI2015—任务查询系统

http://www.lydsy.com/JudgeOnline/problem.php?id=3932 (题目链接) 题意 给出$m$个区间,每个区间有一个权值,$n$组询问,每次询问在位置$x$权值前$k$大的区间的权值和. Solution 扫描线搞一下然后主席树维护即可. 细节 查询的时候注意叶子节的情况 代码 // bzoj3932 #include<algorithm> #include<iostream> #include<cstdlib> #includ