[BZOJ3932]任务查询系统
[BZOJ3932]任务查询系统
题面
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的
任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行
),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。调度系统会经常向
查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个
)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先
级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。
Input
输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。接下来m行,每行包含三个空格
分开的正整数Si、Ei和Pi(Si≤Ei),描述一个任务。接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,
描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci计算得到。其中Pre表示上一次查询的结果,
对于第一次查询,Pre=1。
Output
输出共n行,每行一个整数,表示查询结果。
Sample Input
4 3 1 2 6 2 3 3 1 3 2 3 3 4 3 1 3 2 1 1 3 4 2 2 4 3
Sample Output
2 8 11
Hint
样例解释
K1 = (1*1+3)%2+1 = 1
K2 = (1*2+3)%4+1 = 2
K3 = (2*8+4)%3+1 = 3
对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列
思路
S-开始时间,E-结束时间,P-优先级,X-查询时间点,K-查询的排名
其实就是在一个轴上,寻找覆盖了点\(X\)的权值最小的\(K\)个的权值之和。
那我们考虑搞一个可持久化线段树,然后把所有工作按照优先级排序。按照优先级插入线段树,将\(S_i-E_i\)全部在tag1上+1,在tag2上+\(P_i\)。
然后开始二分,每次判断\(mid\)这个版本\(tag1[X_i]\)的值有没有超过\(K_i\)然后就找到了答案。
特别的,应为\(K_i\)可能会大于\(max(tag1[X_i])\),所以每次查询之前我们先看一下最后一个版本的\(tag1[X_i]\)是不是大于\(K_i\),如果是,直接输出最后一个版本的\(tag2[X_i]\)即可。
代码
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
#define maxn (int)(1e5+1000)
#define ll long long
ll pre,tag2[maxn<<6],sum2[maxn<<6],a,b,c,d;
int rt[maxn],tag1[maxn<<6],ls[maxn<<6],rs[maxn<<6],sum1[maxn<<6];
struct gg{
int s,e;ll p;
}data[maxn];
ll idx;
int n,m;
bool cop(gg x,gg y){
return x.p<y.p;
}
int build(int l,int r){
int now=++idx;
if(l==r)return now;
int mid=(l+r)>>1;
ls[now]=build(l,mid);
rs[now]=build(mid+1,r);
return now;
}
int update(int x,int l,int r,int tl,int tr,int val1,ll val2){
int now=++idx;
ls[now]=ls[x],rs[now]=rs[x],sum1[now]=sum1[x],sum2[now]=sum2[x],tag1[now]=tag1[x],tag2[now]=tag2[x];
sum1[now]=sum1[x]+(min(r,tr)-max(l,tl)+1)*val1;sum2[now]=sum2[x]+(min(r,tr)-max(l,tl)+1)*val2;
int mid=(l+r)>>1;
if(tl<=l&&r<=tr){
tag1[now]+=val1;tag2[now]+=val2;return now;
}
if(tl<=mid){
ls[now]=update(ls[x],l,mid,tl,tr,val1,val2);
}
if(tr>=mid+1){
rs[now]=update(rs[x],mid+1,r,tl,tr,val1,val2);
}
return now;
}
ll query(int x,int l,int r,int tl,int tr,int add1,ll add2,int mod){
if(tl<=l&&r<=tr){
if(mod==1)return add1+sum1[x];
else return add2+sum2[x];
}
add1+=tag1[x];add2+=tag2[x];
ll ans=0;int mid=(l+r)>>1;
if(tl<=mid){
ans+=query(ls[x],l,mid,tl,tr,add1,add2,mod);
}
if(tr>=mid+1){
ans+=query(rs[x],mid+1,r,tl,tr,add1,add2,mod);
}
return ans;
}
int main(){
// /freopen("in","r",stdin);
pre=1;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;i++){
scanf("%d%d%lld",&data[i].s,&data[i].e,&data[i].p);
}
sort(data+1,data+1+m,cop);
rt[0]=build(1,n);
for(int i=1;i<=m;i++){
rt[i]=update(rt[i-1],1,n,data[i].s,data[i].e,1,data[i].p);
}
for(int i=1;i<=n;i++){
scanf("%lld%lld%lld%lld",&d,&a,&b,&c);
ll k=1+(a*pre+b)%c;int l=1,r=m;
while(l<r){
int mid=(l+r+1)>>1;
if(query(rt[mid],1,n,d,d,0,0,1)<=k){
l=mid;
}else{
r=mid-1;
}
}
pre=query(rt[l],1,n,d,d,0,0,2);
printf("%lld\n",pre);
}
return 0;
}