3932: [CQOI2015]任务查询系统
Time Limit: 20 Sec MemoryLimit: 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行,每行一个整数,表示查询结果。
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的一个排列
题目分析:感到稍微有点吃惊,原来人家省的省选居然还有这等数据结构裸题存在……。这题很明显就是可持久化线段树+二叉查找。By the way,我还要说一件很神奇的事情,我原先代码最后cout了一个long long类型交上bzoj,RE了;然后我换成printfI64d之后OLE了;然后我改成printflld,AC了……
CODE:
#include<iostream>
#include<string>
#include<cstring>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<stdio.h>
#include<algorithm>
using namespace std;
const int maxn=100100;
const int maxl=20;
struct Tnode
{
int cnt;
long long sum;
Tnode *lson,*rson;
} tree[ (maxn<<2) + maxn*maxl*2 ];
Tnode *Root[maxn];
int cur;
struct data
{
int val,num,id,t,temp;
} task[maxn<<1];
int P[maxn];
int n,m;
bool Comp1(data x,data y)
{
return x.val<y.val;
}
bool Comp2(data x,data y)
{
return x.t<y.t;
}
Tnode *New_node()
{
cur++;
tree[cur].sum=tree[cur].cnt=0;
tree[cur].lson=tree[cur].rson=tree;
return tree+cur;
}
void Update(Tnode *root,int L,int R,int x,int v1,int v2)
{
if (L==R)
{
root->cnt+=v2;
root->sum+=(long long)(v1*v2);
return;
}
Tnode *new_son=New_node();
int mid=(L+R)>>1;
if (x<=mid)
{
*new_son=*(root->lson);
root->lson=new_son;
Update(new_son,L,mid,x,v1,v2);
}
else
{
*new_son=*(root->rson);
root->rson=new_son;
Update(new_son,mid+1,R,x,v1,v2);
}
root->cnt=root->lson->cnt+root->rson->cnt;
root->sum=root->lson->sum+root->rson->sum;
}
long long Query(Tnode *root,int L,int R,long long k)
{
if (L==R)
{
if (k>=(long long)root->cnt) return root->sum;
else return 0;
}
long long left_cnt=root->lson->cnt;
int mid=(L+R)>>1;
if (k>left_cnt) return root->lson->sum+Query(root->rson,mid+1,R,k-left_cnt);
else return Query(root->lson,L,mid,k);
}
int main()
{
freopen("bzoj3932.in","r",stdin);
freopen("bzoj3932.out","w",stdout);
scanf("%d%d",&m,&n);
for (int i=1; i<=m; i++)
{
int s,e,p;
scanf("%d%d%d",&s,&e,&p);
e++;
int x=i<<1;
x--;
task[x].val=p;
task[x].t=s;
task[x].num=1;
task[x].temp=i;
x++;
task[x].val=p;
task[x].t=e;
task[x].num=-1;
task[x].temp=i;
}
sort(task+1,task+(m<<1)+1,Comp1);
cur=0;
for (int i=1; i<=(m<<1); i++)
if (!P[ task[i].temp ])
{
cur++;
task[i].id=P[ task[i].temp ]=cur;
}
else task[i].id=P[ task[i].temp ];
sort(task+1,task+(m<<1)+1,Comp2);
//for (int i=1; i<=(m<<1); i++) printf("%d %d %d %d\n",task[i].val,task[i].num,task[i].id,task[i].t);
cur=-1;
Root[0]=New_node();
int tail=0;
for (int i=1; i<=n; i++)
{
Tnode *x=Root[i-1];
while ( task[tail+1].t<=i && tail<(m<<1) )
{
Tnode *y=New_node();
*y=*x;
tail++;
Update(y,1,n,task[tail].id,task[tail].val,task[tail].num);
x=y;
}
Root[i]=x;
}
long long pre=1;
for (int i=1; i<=n; i++)
{
int x,a,b,c;
scanf("%d%d%d%d",&x,&a,&b,&c);
long long k=1LL+((long long)a*pre+(long long)b)%(long long)c;
//cout<<k<<' '<<x<<endl;
pre=Query(Root[x],1,n,k);
printf("%lld\n",pre);
}
return 0;
}