区间修改+单点查询
利用时间点建树,因为主席树建树时第i结点会继承第i-1个结点的信息,可以只修改区间端点使每个时间点对应的树恰好表示该时间的任务优先级情况。
1.把区间端点全部放入数组task中排序,起始点时间不变,结束点时间加一。
2.按时间从1到n建树,每次建树把task中所有时间为i的结点建到树里,起始点加入树(标记为1),结束点在树中减去(标为-1)
3.直接查询时间点对应的那棵树即可
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
int n,dis[100010],cnt=1,rt[100010];
struct Task
{
int s,p,h;
bool operator <(const Task &jkl)const
{
return s<jkl.s;
}
}task[200010];
struct node
{
int l,r,t;
ll sum,v;
}tree[100010*40];
void add(int l,int r,int &rt,int q,int k,ll p,ll h,int t)
{
if(tree[rt].t!=t)
{
rt=cnt++;
tree[rt]=tree[q];
tree[rt].t=t;
}
if(l==r)
{
tree[rt].v+=h;
tree[rt].sum+=h*p;
return;
}
int mid=(l+r)>>1;
if(k<=mid)
add(l,mid,tree[rt].l,tree[q].l,k,p,h,t);
else
add(mid+1,r,tree[rt].r,tree[q].r,k,p,h,t);
tree[rt].v=tree[tree[rt].l].v+tree[tree[rt].r].v;
tree[rt].sum=tree[tree[rt].l].sum+tree[tree[rt].r].sum;
}
ll query(int l,int r,int q,int k)
{
if(l==r)
{
if(!tree[q].sum)
return 0;
else
return tree[q].sum/tree[q].v*k;
}
int sum=tree[tree[q].l].v,mid=(l+r)>>1;
if(k<=sum)
return query(l,mid,tree[q].l,k);
else
return tree[tree[q].l].sum+query(mid+1,r,tree[q].r,k-sum);
}
int main()
{
//freopen("1.txt","r",stdin);
int m,con=1;
ll ans=1;
scanf("%d%d",&m,&n);
for(int i=1;i<=m;++i)
{
scanf("%d%d%d",&task[con].s,&task[con+1].s,&task[con].p);
dis[i]=task[con].p;
task[con++].h=1;
task[con].p=task[con-1].p;
++task[con].s;
task[con++].h=-1;
}
sort(dis+1,dis+m+1);
sort(task+1,task+con);
int ed=unique(dis+1,dis+m+1)-dis-1;
task[con].s=-1;
int id=1;
for(int i=1;i<=n;++i)
{
int f=0;
while(task[id].s==i)
{
int mid=lower_bound(dis+1,dis+ed+1,task[id].p)-dis;
f=1;
add(1,ed,rt[i],rt[i-1],mid,task[id].p,task[id].h,i);
++id;
}
if(!f)
rt[i]=rt[i-1];
}
while(n--)
{
int x;
ll k,a,b,c;
scanf("%d%lld%lld%lld",&x,&a,&b,&c);
k=1+(a*ans+b)%c;
ans=query(1,ed,rt[x],k);
printf("%lld\n",ans);
}
return 0;
}