题意描述:
每一个任务有三个属性: \(s,t,w\) , 表示这个任务会在 \(s-t\) 这一段时间内运行,优先度为 \(w\) .
有 \(q\) 组询问,每次询问你 第 \(x\) 秒运行的任务的优先度前 \(k\) 小的任务的优先度之和。
数据范围: \(n,m\leq 10^5 , w\leq 10^9\)
solution:
有一个很 \(naive\) 的想法,对于每个任务把他 插入到 \(s-t\) 当中, 对于每一时刻开个权值线段树,权值为每个任务的优先度,每次询问就相当于在权值线段树上找前 \(k\) 小的数的和。
暴力插的复杂度肯定不对,考虑怎么优化一下。
我们维护的是每个时刻优先度为 \(w\) 的任务的个数,那么一个任务对 \(s-t\) 会有 \(1\) 的贡献。
区间加 \(1\) ,很容易想到差分, 然后维护一下前缀和。
拿主席树来维护一下,每次询问就在主席树上二分查找就好了。
注意:每次修改都要新建一个版本,不然会导致节点的信息出错。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<vector>
using namespace std;
#define int long long
const int N = 2e5+10;
const int inf = 1e7+10;
int n,m,tot,s,t,p,x,a,b,c,k,cnt,last = 1,rt[N<<2],B[N];
vector<pair<int,int> > v[N];
struct Tree
{
int lc,rc,siz,sum;
}tr[40000000];
inline int read()
{
int s = 0,w = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') w = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){s = s * 10 + ch - '0'; ch = getchar();}
return s * w;
}
void up(int o)
{
tr[o].siz = tr[tr[o].lc].siz + tr[tr[o].rc].siz;
tr[o].sum = tr[tr[o].lc].sum + tr[tr[o].rc].sum;
}
int insert(int &o,int last,int l,int r,int x,int val)
{
o = ++tot;
if(l == r)
{
tr[o].siz = tr[last].siz + val;
tr[o].sum = tr[last].sum + val * B[l];
return o;
}
tr[o].lc = tr[last].lc;
tr[o].rc = tr[last].rc;
int mid = (l + r)>>1;
if(x <= mid) tr[o].lc = insert(tr[o].lc,tr[last].lc,l,mid,x,val);
if(x > mid) tr[o].rc = insert(tr[o].rc,tr[last].rc,mid+1,r,x,val);
up(o);
return o;
}
int query(int o,int l,int r,int k)
{
if(!o) return 0;
if(l == r && tr[o].siz >= k) return k * B[l];
else if(l == r) return tr[o].sum;
if(tr[o].siz <= k) return tr[o].sum;
int mid = (l + r)>>1;
if(tr[tr[o].lc].siz >= k) return query(tr[o].lc,l,mid,k);
else return tr[tr[o].lc].sum + query(tr[o].rc,mid+1,r,k-tr[tr[o].lc].siz);
}
signed main()
{
m = read(); n = read();
for(int i = 1; i <= m; i++)
{
s = read(); t = read(); p = read();
B[++cnt] = p;
v[s].push_back(make_pair(p,1));
v[t+1].push_back(make_pair(p,-1));
}
sort(B+1,B+cnt+1);
int num = unique(B+1,B+cnt+1)-B-1;
for(int i = 1; i <= n; i++)
{
rt[i] = rt[i-1];
for(int j = 0; j < v[i].size(); j++)
{
int pos = lower_bound(B+1,B+num+1,v[i][j].first)-B;
rt[i] = insert(rt[i],rt[i],1,num,pos,v[i][j].second);
}
}
for(int i = 1; i <= n; i++)
{
x = read(); a = read(); b = read(); c = read();
k = 1 + (a * last % c + b) % c;
last = query(rt[x],1,num,k);
printf("%lld\n",last);
}
return 0;
}