欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ3932
题意概括
电脑有N个任务需要执行,任务i在li到ri时正在工作,优先级为p。 现在给出M个询问,每个询问给出一个时间点xi和一个数ki。问在xi这个时间点时,所有正在工作的任务中优先级从小到大排列,前ki个的优先级之和是多少。 强制在线。 N<=100 000,M<=100 000
题解
用差分的思想,在Li的地方加,在Ri的地方减。
然后就是裸的主席树。
有坑。
这题细节丧病。
首先,我把n和m反着写,然后还以为时间点是n(我的n),事实上是我的m。
其次,还会出现同一个时间点多个事件,要考虑,所以对于长度为1的区间,要sum/size*k
当然,事情还没有结束。
size有可能是0,要特判。
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <vector>
using namespace std;
typedef long long LL;
const int N=100005;
int n,m,Ha[N],hs;
vector <int> tz[N];
struct Task{
int L,R,P;
void Read(){
scanf("%d%d%d",&L,&R,&P);
}
}t[N];
void LSH(){
int hs_=1;
sort(Ha+1,Ha+hs+1);
for (int i=2;i<=hs;i++)
if (Ha[i]!=Ha[i-1])
Ha[++hs_]=Ha[i];
hs=hs_;
}
const int S=N*4*20;
int ls[S],rs[S],size[S],total,root[N];
LL sum[S];
int find(int v){
return lower_bound(Ha+1,Ha+hs+1,v)-Ha;
}
void build(int &rt,int L,int R){
rt=++total;
if (L==R)
return;
int mid=(L+R)>>1;
build(ls[rt],L,mid);
build(rs[rt],mid+1,R);
}
void add(int prt,int &rt,int L,int R,int pos,LL v,int op){
if (!rt||rt==prt)
rt=++total,sum[rt]=sum[prt],size[rt]=size[prt];
sum[rt]+=v,size[rt]+=op;
if (L==R)
return;
int mid=(L+R)>>1;
if (!ls[rt])
ls[rt]=ls[prt];
if (!rs[rt])
rs[rt]=rs[prt];
if (pos<=mid)
add(ls[prt],ls[rt],L,mid,pos,v,op);
else
add(rs[prt],rs[rt],mid+1,R,pos,v,op);
}
LL query(int rt,int L,int R,int k){
if (L==R){
k=min(k,size[rt]);
if (size[rt]==0)
return 0;
return sum[rt]*k/size[rt];
}
int Lz=size[ls[rt]];
int mid=(L+R)>>1;
if (Lz>=k)
return query(ls[rt],L,mid,k);
else
return sum[ls[rt]]+query(rs[rt],mid+1,R,k-Lz);
}
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;i++){
t[i].Read();
Ha[i]=t[i].P;
}
hs=n;
LSH();
for (int i=1;i<=m+1;i++)
tz[i].clear();
for (int i=1;i<=n;i++){
tz[t[i].L].push_back(i);
tz[t[i].R+1].push_back(i);
t[i].P=find(t[i].P);
}
total=0;
build(root[0],1,hs);
for (int i=1;i<=m;i++){
root[i]=root[i-1];
for (int j=0;j<tz[i].size();j++){
int k=tz[i][j];
if (t[k].L==i)
add(root[i-1],root[i],1,hs,t[k].P,Ha[t[k].P],1);
else
add(root[i-1],root[i],1,hs,t[k].P,-Ha[t[k].P],-1);
}
}
LL pre=1;
for (int i=1;i<=m;i++){
int x,A,B,C,k;
scanf("%d%d%d%d",&x,&A,&B,&C);
k=(pre*A+B)%C+1;
printf("%lld\n",pre=query(root[x],1,hs,k));
}
return 0;
}