您的位置:首页 > 其它

NKOJ3251 (CQOI2015) 任务查询系统(差分数组,主席树)

2017-07-19 17:29 381 查看

问题描述


        最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。

        超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi。同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同。

        调度系统会经常向查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少。特别的,如果Ki大于第Xi秒正在运行的任务总数,则直接回答第Xi秒正在运行的任务优先级之和。上述所有参数均为整数,时间的范围在1到n之间(包含1和n)。


输入格式


        输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。

        接下来m行,每行包含三个空格分开的正整数Si,Ei和Pi(Si≤Ei),描述一个任务。

        接下来n行,每行包含四个空格分开的整数Xi,Ai,Bi和Ci,描述一次查询。查询的参数Ki需要由公式
Ki = 1 + ( Ai * Pre + Bi )
mod Ci 计算得到。其中Pre表示上一次查询的结果,对于第一次查询,Pre=1。


输出格式


        输出共n行,每行一个整数,表示查询结果。


样例输入


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


样例输出


2

8

11


提示


样例解释:

        K1=(1*1+3)%2+1=1;

        K2=(1*2+3)%4+1=2;

        K3=(2*8+4)%3+1=3。

数据范围:

        对于50%的数据,Ai=0。

        对于100%的数据,1≤m,n,Si,Ei,Ci≤100000,0≤Ai,Bi≤100000,1≤Pi≤10000000,Xi为1到n的一个排列。

    求前K小的和,实际上和求第K小一样,过程中累加一下sum就好。

    然后根据时间建立n棵主席树,每个任务会修改Si到Ei这么多数,区间修改,用一点差分的思想相当于是在第Si棵树上加,在第Ei+1棵树上减,最后求个前缀就好。

    具体实现时只需要按照操作的时间排序后不断加入就好。当将时间在Xi前的操作全部加入树上后得到的就是Xi时间的树。

    最后说一下,因为在查询答案时到达底层节点时要取得前K个,所以需要将sum/cnt*k。(亲测乱写能得80分)

附上代码

#include<stdio.h>
#include<iostream>
#include<algorithm>
#define ll long long
#define M 20000000
#define N 300000
using namespace std;
struct node{ll x,y,ny,d;}A
;
bool cmp(node a,node b)
{return a.x<b.x;}
ll B
,rt
,m,n,pre=1;
ll ls[M],rs[M],cnt[M],sum[M],tot;
ll CO(ll p)
{
ll o=++tot;
ls[o]=ls[p];rs[o]=rs[p];
cnt[o]=cnt[p];sum[o]=sum[p];
return o;
}
ll ADD(ll p,ll l,ll r,ll k,ll sd,ll cd)
{
ll o=CO(p);
if(l==r){cnt[o]+=cd;sum[o]+=cd*sd;}
else
{
ll mid=l+r>>1;
if(k<=mid)ls[o]=ADD(ls[o],l,mid,k,sd,cd);
else rs[o]=ADD(rs[o],mid+1,r,k,sd,cd);
cnt[o]=cnt[ls[o]]+cnt[rs[o]];
sum[o]=sum[ls[o]]+sum[rs[o]];
}
return o;
}
ll ASK(ll p,ll l,ll r,ll k)
{
if(l==r)return sum[p]/cnt[p]*k;
ll mid=l+r>>1;
if(cnt[ls[p]]>=k)return ASK(ls[p],l,mid,k);
return ASK(rs[p],mid+1,r,k-cnt[ls[p]])+sum[ls[p]];
}
int main()
{
ll i,j=1,k,p,a,b,c;
scanf("%lld%lld",&m,&n);
for(i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&a,&b,&c);
B[i]=c;
A[i].x=a;A[i].y=c;A[i].d=1;
A[i+m].x=b+1;A[i+m].y=c;A[i+m].d=-1;
}
sort(B+1,B+m+1);
sort(A+1,A+2*m+1,cmp);
for(i=1;i<=2*m;i++)A[i].ny=lower_bound(B+1,B+m+1,A[i].y)-B;
for(i=1;i<=n;i++)
{
rt[i]=rt[i-1];j--;
while(A[++j].x==i)rt[i]=ADD(rt[i],1,m,A[j].ny,A[j].y,A[j].d);
}
for(i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&k,&a,&b,&c);
p=1+(a*pre+b)%c;
if(p>cnt[rt[k]])pre=sum[rt[k]];
else pre=ASK(rt[k],1,m,p);
printf("%lld\n",pre);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: