3932: [CQOI2015]任务查询系统

3932: [CQOI2015]任务查询系统

Time Limit: 20 Sec   Memory Limit: 512 MB
Submit: 1191   Solved: 437
[ 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

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的一个排列

Source

[ Submit][ Status][ Discuss]



用主席树解决

对时间建立主席树,每个节点储存当前值域含有的值的总数以及他们的和

这样每个任务就拆为Si、Ei两处的一个+操作和一个-操作

然后查询


空间开小:操作数*2所以空间应该2*nlogn...

查询出错:每个时间可能有多个重复优先级任务,所以查询需要特判这一点,否则出差错


#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

typedef long long LL;
const int maxn = 2E5 + 10;

struct data{
	LL sum; int tot;
}c[maxn*20];

LL num[maxn];
int n,m,cnt,cur = 1,lc[maxn*20],rc[maxn*20],root[maxn];
vector  v[maxn];

LL getLL()
{
	LL ret = 0;
	char ch = getchar();
	while (ch < '0' || '9' < ch) ch = getchar();
	while ('0' <= ch && ch <= '9') ret = ret*10 + 1LL*(ch-'0'),ch = getchar();
	return ret;
}

int ABS(int x) {return x > 0?x:-x;}

int Insert(int o,int l,int r,int po)
{
	int ret = ++cnt;
	if (po < 0) c[ret].sum = c[o].sum - num[-po],c[ret].tot = c[o].tot - 1;
	else c[ret].sum = c[o].sum + num[po],c[ret].tot = c[o].tot + 1;
	if (l == r) return ret;
	int pos = ABS(po);
	int mid = (l+r) >> 1;
	if (pos <= mid) rc[ret] = rc[o],lc[ret] = Insert(lc[o],l,mid,po);
	else lc[ret] = lc[o],rc[ret] = Insert(rc[o],mid+1,r,po);
	return ret;
}

LL query(int o,int l,int r,int k)
{
	if (c[o].tot <= k) return c[o].sum;
	if (l == r) return 1LL*k*num[l];
	int left = c[lc[o]].tot;
	int mid = (l+r) >> 1;
	if (left >= k) return query(lc[o],l,mid,k);
	else return c[lc[o]].sum + query(rc[o],mid+1,r,k-left);
}

int main()
{
	#ifdef YZY
		   freopen("yzy.txt","r",stdin);
	#endif
	
	cin >> m >> n;
	for (int i = 0; i < m; i++) {
		int x = getLL(),y = getLL(),z = getLL();
		v[x].push_back(z); v[y+1].push_back(-z);
		num[i+1] = z;
	}
	sort(num + 1,num + m + 1);
	for (int i = 2; i <= m; i++)
		if (num[i] != num[i-1])
			num[++cur] = num[i];
	for (int i = 1; i <= n; i++)
		for (int j = 0; j < v[i].size(); j++) {
			int x = v[i][j];
			int pos = lower_bound(num + 1,num + cur + 1,ABS(x)) - num;
			v[i][j] = x > 0?pos:-pos;
		}
	for (int i = 1; i <= n; i++) {
		if (v[i].size()) {
			for (int j = 0; j < v[i].size(); j++) {
				int po = !j?root[i-1]:root[i];
				root[i] = Insert(po,1,cur,v[i][j]);
			}
		}
		else root[i] = root[i-1];
	}
	
	LL Pre = 1;
	for (int i = 0; i < n; i++) {
		int X; LL A,B,C;
		X = getLL(); A = getLL();
		B = getLL(); C = getLL();
		int K = 1 + (Pre*A + B) % C;
		Pre = query(root[X],1,cur,K);
		printf("%lld\n",Pre);
	}
	return 0;
}


你可能感兴趣的:(主席树)