zoukankan      html  css  js  c++  java
  • [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
    ",pre);
    	}
    	return 0;
    }
    
  • 相关阅读:
    《软件工程》第八章随笔
    《软件工程》第七章随笔
    《软件工程》第六章随笔
    《软件工程》-第五章随笔
    自动生成小学四则运算题目
    人月神话
    软件工程——理论、方法与实践11
    软件工程——理论、方法与实践⑩
    软件工程——理论、方法与实践⑨
    软件工程——理论、方法与实践⑧
  • 原文地址:https://www.cnblogs.com/GavinZheng/p/10854717.html
Copyright © 2011-2022 走看看