3932: [CQOI2015]任务查询系统
Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3412 Solved: 1098
[ Submit][ Status][ Discuss]
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
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
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的一个排列
这道laji题,对拍对了我20h。
然后...........数组开小了。(我能怎么办,我也很绝望啊!)
题解:
以时间为下标,优先级为区间建主席树。
对于s1,e1,p1,
我们可以在s1时加上p1,e1+1时减去p1
维护区间和以及个数就好了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
const ll N=8000001;
const ll M=300010;
struct node{
ll l,r,l1,r1,x;
ll s;
}tr[N];ll tot=0,root[N];
ll m,n;
struct node1{
ll s,p,x,k;
}sa[M];
struct node2{
ll s,e,p,x;
}a[M];
bool cmp(node2 x,node2 y)
{
return x.p<y.p;
}
void built(ll l,ll r)
{
tot++;
ll now=tot;
tr[now].l=l;tr[now].r=r;
if(l!=r)
{
ll mid=(l+r)>>1;
tr[now].l1=tot+1;built(l,mid);
tr[now].r1=tot+1;built(mid+1,r);
}
}
inline ll ins(ll rt,ll l,ll r,ll p,ll x)
{
if(rt==0) return 0;
if(l<=tr[rt].l&&tr[rt].r<=r)
{
tot++;
tr[tot].l=l;tr[tot].r=r;
tr[tot].s=tr[rt].s+p*x;
tr[tot].x=tr[rt].x+x;
return tot;
}
else
{
//prllf("!");
tot++;
ll pp=tot;
tr[pp].l=tr[rt].l;
tr[pp].r=tr[rt].r;
ll mid=(tr[rt].l+tr[rt].r)/2;
if(l<=mid)
{
tr[pp].l1=ins(tr[rt].l1,l,r,p,x);
tr[pp].r1=tr[rt].r1;
}
if(r>mid)
{
tr[pp].l1=tr[rt].l1;
tr[pp].r1=ins(tr[rt].r1,l,r,p,x);
}
tr[pp].s=tr[tr[pp].l1].s+tr[tr[pp].r1].s;
tr[pp].x=tr[tr[pp].l1].x+tr[tr[pp].r1].x;
return pp;
}
}
long long f[100001],fx[100001];
ll getans(ll rt,ll k)
{
if(tr[rt].l==tr[rt].r)
{
return f[tr[rt].l]*k;
}
if(tr[rt].x<=k)
return tr[rt].s;
if(tr[tr[rt].l1].x<k)
return tr[tr[rt].l1].s+getans(tr[rt].r1,k-tr[tr[rt].l1].x);
return getans(tr[rt].l1,k);
}
bool cmp2(node1 x,node1 y)
{
return x.s<y.s;
}
int main()
{
scanf("%lld%lld",&m,&n);
ll s1,e1,p1;
for(ll i=1;i<=m;i++)
{
scanf("%lld%lld%lld",&a[i].s,&a[i].e,&a[i].p);
a[i].x=i;
}
sort(a+1,a+1+m,cmp);
ll p=0;
p++;
f[p]=a[1].p;
fx[a[1].x]=p;
for(ll i=2;i<=m;i++)
{
if(a[i].p!=a[i-1].p)
{
p++;
f[p]=a[i].p;
}
fx[a[i].x]=p;
}
ll tx=0;
for(ll i=1;i<=m;i++)
{
tx++;
sa[tx].s=a[i].s;
sa[tx].p=a[i].p;
sa[tx].x=1;
sa[tx].k=fx[a[i].x];
tx++;
sa[tx].s=a[i].e+1;
sa[tx].p=a[i].p;
sa[tx].x=-1;
sa[tx].k=fx[a[i].x];
}
sort(sa+1,sa+1+tx,cmp2);
root[0]=tot+1;
built(1,p);
ll lar=root[0];
for(ll i=1;i<=tx;i++)
{
ll tp=tot+1;
ll yu=ins(lar,sa[i].k,sa[i].k,sa[i].p,sa[i].x);
root[sa[i].s]=tp;
lar=tp;
}
for(int i=1;i<=sa[tx].s;i++)
if(root[i]==0)
root[i]=root[i-1];
ll x1,a1,b1,c1,k1;
long long pre=1;
for(ll i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&x1,&a1,&b1,&c1);
k1=1+(a1*pre+b1)%c1;
pre=getans(root[x1],k1);
printf("%lld\n",pre);
}
}