您的位置:首页 > 其它

3932: [CQOI2015]任务查询系统

2016-04-03 13:50 471 查看

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<iostream>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
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 <LL> 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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: