3932: [CQOI2015]任务查询系统
Time Limit: 20 Sec Memory Limit: 512 MB
Submit: 4713 Solved: 1588
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行,每行一个整数,表示查询结果。
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的一个排列
解析:
主席树。
首先暴力 L~R 依次修改肯定是不行的,所以我们可以用类似差分的思想,在 L 处加上这个数,在 R+1 处减去这个数,然后从1~m 扫一遍建树就可以了,询问就是很常规的问题了。
代码:
#include <bits/stdc++.h>
#define LL long long
using namespace std;
const int Max=100100;
int n,m,q,sz,mn=1e8,mx=-1e8,mark;
int root[Max*50],flag[Max*50];
LL p=1;
struct shu{int l,r,size;LL sum;};
shu tree[Max*50];
vector<int>s[Max],t[Max];
inline LL get_int()
{
LL x=0,f=1;
char c;
for(c=getchar();(!isdigit(c))&&(c!='-');c=getchar());
if(c=='-') {f=-1;c=getchar();}
for(;isdigit(c);c=getchar()) x=(x<<3)+(x<<1)+c-'0';
return x*f;
}
inline void NEW(int &rt,int fa){tree[rt=++sz]=tree[fa];flag[rt]=mark;}
inline void build(int &root,int fa,int l,int r,int num,int f)
{
if(flag[fa]!=mark) NEW(root,fa);
tree[root].sum+=(LL)f*num,tree[root].size+=f;
if(l==r) return;
int mid = l + r >> 1;
if(num <= mid) build(tree[root].l,tree[fa].l,l,mid,num,f);
else build(tree[root].r,tree[fa].r,mid+1,r,num,f);
}
inline LL Q(int root,int l,int r,int k)
{
if(l==r) return (LL)l*k; //注意不能返回sum[root]!!
int mid = l + r >> 1;
if(k <= tree[tree[root].l].size) return Q(tree[root].l,l,mid,k);
else return (LL)Q(tree[root].r,mid+1,r,k-tree[tree[root].l].size) + tree[tree[root].l].sum;
}
int main()
{
n=get_int(),m=get_int();
for(int i=1;i<=n;i++)
{
int x=get_int(),y=get_int(),z=get_int();
mn=min(mn,x),mx=max(mx,y+1);
s[x].push_back(z),t[y].push_back(z);
}
for(int i=mn;i<=mx+1;i++)
{
NEW(root[i],root[i-1]),mark++;
for(int j=0;j<s[i].size();j++) build(root[i],root[i],1,1e7,s[i][j],1);
for(int j=0;j<t[i-1].size();j++) build(root[i],root[i],1,1e7,t[i-1][j],-1);
}
for(int i=1;i<=m;i++)
{
LL x=get_int(),a=get_int(),b=get_int(),c=get_int(),k=1+(a*p+b)%c;
if(tree[root[x]].size <= k) cout<<(p=tree[root[x]].sum)<<"\n";
else cout<<(p=Q(root[x],1,1e7,k))<<"\n";
}
return 0;
}