Time Limit: 20 Sec
Memory Limit: 512 MB
Description
最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。超级计算机中的
任务用三元组(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行,每行一个整数,表示查询结果。
HINT
对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列
题目分析
优先级pi先离散化
主席树维护时间轴,每棵权值线段树对应的是优先级的出现情况
size记录区间出现不同任务的数量,sum记录区间优先级之和
因为每个任务是一段区间,所以先差分再建主席树
#include<iostream>
#include<cstdio>
#include<cmath>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long lt;
#define lowbit(x) ((x)&(-x))
int read()
{
int f=1,x=0;
char ss=getchar();
while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();}
while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();}
return f*x;
}
const int maxN=2e5+10;
const int maxM=2e7+10;
int n,m;
int rt[maxM],ch[maxM][2],sz;
int size[maxM],RT[maxN];
lt sum[maxM];
int Si[maxN],Ei[maxN],pi[maxN];
int b[maxN],pos[maxN],cnt,tot;
struct node{int pos,val,k;}rem[maxN<<1];
lt ans=1;
bool cmp(node a,node b){ return a.pos<b.pos;}
int update(int pre,int ll,int rr,int x,int k)
{
int tt=++sz; size[tt]=size[pre]+k; sum[tt]=sum[pre]+1ll*pos[x]*k;
ch[tt][0]=ch[pre][0]; ch[tt][1]=ch[pre][1];
int mid=ll+rr>>1;
if(ll<rr)
{
if(x<=mid) ch[tt][0]=update(ch[pre][0],ll,mid,x,k);
else ch[tt][1]=update(ch[pre][1],mid+1,rr,x,k);
}
return tt;
}
lt query(int u,int ll,int rr,int k)
{
if(ll==rr) return 1ll*k*pos[ll];
int mid=ll+rr>>1;
if(k<=size[ch[u][0]]) return query(ch[u][0],ll,mid,k);
else return sum[ch[u][0]]+query(ch[u][1],mid+1,rr,k-size[ch[u][0]]);
}
int main()
{
m=read();n=read();
for(int i=1;i<=m;++i)
{
Si[i]=read(); Ei[i]=read();
pi[i]=b[i]=read();
}
sort(b+1,b+1+m);
for(int i=1;i<=m;++i)
if(i==1||b[i]!=b[i-1])
pos[++cnt]=b[i];
for(int i=1;i<=m;++i)
{
pi[i]=lower_bound(pos+1,pos+1+cnt,pi[i])-pos;
rem[++tot]=(node){Si[i],pi[i],1};
rem[++tot]=(node){Ei[i]+1,pi[i],-1};
}
sort(rem+1,rem+1+2*m,cmp);
int tt=1,rtn=0;
for(int i=1;i<=n+1;++i)//差分后时间轴+1
{
while(tt<=tot&&rem[tt].pos==i)
rt[rtn+1]=update(rt[rtn],1,cnt,rem[tt].val,rem[tt].k),tt++,rtn++;
RT[i]=rt[rtn];
}
for(int i=1;i<=n;++i)
{
lt Xi=read(),Ai=read(),Bi=read(),Ci=read();
lt Ki=1+(Ai*ans+Bi)%Ci;
if(size[RT[Xi]]<=Ki) ans=sum[RT[Xi]];//-sum[RT[Xi-1]];
else ans=query(RT[Xi],1,cnt,Ki);
printf("%lld\n",ans);
}
return 0;
}