[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;
}
posted @ 2019-05-13 08:18  GavinZheng  阅读(302)  评论(0编辑  收藏  举报