bzoj3932:任务查询系统(可持久化线段树)

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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值