bzoj3932

3932: [CQOI2015]任务查询系统

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

主席树 

差分思想 然后对于每个任务分成两个 一次减一次加 主席树插入具体看代码 注意每次查询的时候必须用l和r 因为不用的话可能同一个任务有很多种 无法通过size判断结束 如果已经走到了l==r 不用lr的话就可能继续走下去 还有rank可能比size小

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 200010;
int n, m, cnt;
ll pre = 1;
int root[N], size[N * 20], lc[N * 20], rc[N * 20];
ll sum[N * 20]; 
struct data {
    int p, t;
}; 
map<int, int> rnk;
vector<int> p;
vector<int> t[N];
namespace tree
{
    void build(int l, int r, int &x)
    {
        x = ++cnt;
        if(l == r) return;
        int mid = (l + r) >> 1;
        build(l, mid, lc[x]); build(mid + 1, r, rc[x]);
    }
    void update(int l, int r, int &x, int last, int pos, int delta, int f)
    {
        x = ++cnt; lc[x] = lc[last]; rc[x] = rc[last];
        size[x] = size[last] + f;
        sum[x] = sum[last] + delta;
        if(l == r) return;
        int mid = (l + r) >> 1;
        if(pos <= mid) update(l, mid, lc[x], lc[last], pos, delta, f);
        else update(mid + 1, r, rc[x], rc[last], pos, delta, f);
    }
    ll query(int l, int r, int x, int rank)
    {
        if(rank >= size[x]) return sum[x];
        if(l == r) return sum[x] * rank / size[x];
        int t = size[lc[x]], mid = (l + r) >> 1;
        if(t >= rank) return query(l, mid, lc[x], rank);
        else return query(mid + 1, r, rc[x], rank - t) + sum[lc[x]];
    }
} using namespace tree;
int main()
{
//    freopen("cqoi15_query.in", "r", stdin);
//    freopen("cqoi15_query.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);
        p.push_back(P);
        t[s].push_back(P);
        t[e + 1].push_back(-P);
    }
    sort(p.begin(), p.end());
    p.erase(unique(p.begin(), p.end()), p.end());    
    for(int i = 0; i < p.size(); ++i) rnk[p[i]] = i + 1;
    build(1, m, root[0]);
    for(int i = 1; i <= n; ++i) 
    {
        if(t[i].empty()) { root[i] = root[i - 1]; continue; }
        update(1, m, root[i], root[i - 1], rnk[abs(t[i][0])], t[i][0], (t[i][0] > 0 ? 1 : -1));
        for(int j = 1; j < t[i].size(); ++j) 
        {
            int node = 0;
//            printf("pos=%d t[i][j]=%d\n", rnk[abs(t[i][j])], t[i][j]);
            update(1, m, node, root[i], rnk[abs(t[i][j])], t[i][j], (t[i][j] > 0 ? 1 : -1));
            root[i] = node;
        }
    }
    for(int i = 1; i <= n; ++i)
    {
        int x, a, b, c;
        scanf("%d%d%d%d", &x, &a, &b, &c);
        int k = 1 + ((ll)a * pre + (ll)b) % (ll)c;
        pre = query(1, m, root[x], k);
        printf("%lld\n", pre);
    } 
//    fclose(stdin); fclose(stdout);
    return 0;
}
View Code

 

posted @ 2017-04-20 17:04  19992147  阅读(185)  评论(0编辑  收藏  举报