bzoj 3932 [CQOI2015]任務查詢系統 主席樹

題目:

http://www.lydsy.com/JudgeOnline/problem.php?id=3932

題意:

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行,每行一個整數,表示查詢結果。

思路:

首先把優先級離散化,然後用差分數組的思想,更新到主席樹上去,主席樹維護兩個值,管轄區間的區間和與管轄區間內元素個數。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 10, INF = 0x3f3f3f3f;

struct node
{
    int x, tp, p, v;
}a[N*2];

int lson[N*50], rson[N*50], siz[N*50];
ll sum[N*50];
int root[N];
int b[N], c[N], d[N];
int tot;
bool _cmp_(int x, int y)
{
    return d[x] < d[y];
}
bool cmp(node a, node b)
{
    return a.x < b.x;
}
void update(int &x, int last, int l, int r, int val, int v1, int v2)
{
    x = ++tot;
    lson[x] = lson[last], rson[x] = rson[last], sum[x] = sum[last]+v1, siz[x] = siz[last]+v2;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(val <= mid) update(lson[x], lson[last], l, mid, val, v1, v2);
    else update(rson[x], rson[last], mid+1, r, val, v1, v2);
}
ll query(int x, int l, int r, int k)
{
    if(l == r) return sum[x];
    int mid = (l + r) >> 1;
    if(k <= siz[lson[x]]) return query(lson[x], l, mid, k);
    else return sum[lson[x]] + query(rson[x], mid+1, r, k - siz[lson[x]]);
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    int x, y, z, num = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d%d", &x, &y, &z);
        b[i] = i, d[i] = z;
        a[++num].x = x, a[num].p = z, a[num].v = 1;
        a[++num].x = y+1, a[num].p = -z, a[num].v = -1;
    }
    //這份代碼對離散化有要求,要求離散化後相同的值不一樣,即離散化結果爲1~n,否則會出錯
    sort(b + 1, b + 1 + n, _cmp_);
    for(int i = 1; i <= n; i++) c[b[i]] = i;
    num = 0;
    for(int i = 1; i <= n; i++) a[++num].tp = c[i], a[++num].tp = c[i];
    sort(a + 1, a + 1 + num, cmp);
    int j = 1;
    for(int i = 1; i <= m; i++)
    {
        root[i] = root[i-1];
        while(a[j].x == i) update(root[i], root[i], 1, n, a[j].tp, a[j].p, a[j].v), j++;
    }
    ll ans = 1;
    for(int i = 1; i <= m; i++)
    {
        int x, a, b, c;
        scanf("%d%d%d%d", &x, &a, &b, &c);
        int k = 1 + (a * ans + b) % c;
        ans = query(root[x], 1, n, k);
        printf("%lld\n", ans);
    }
    return 0;
}

另外一種寫法,首先也是離散化優先級,主席樹只維護所管轄區間的元素個數,查詢的時候,一直查詢到葉節點

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int N = 100000 + 10, INF = 0x3f3f3f3f;

struct node
{
    int x, tp, p, v;
}a[N*2];

int lson[N*50], rson[N*50], siz[N*50];
int root[N];
int b[N], c[N], d[N];
int tot;
bool cmp(node a, node b)
{
    return a.x < b.x;
}
void update(int &x, int last, int l, int r, int val, int v)
{
    x = ++tot;
    lson[x] = lson[last], rson[x] = rson[last], siz[x] = siz[last]+v;
    if(l == r) return;
    int mid = (l + r) >> 1;
    if(val <= mid) update(lson[x], lson[last], l, mid, val, v);
    else update(rson[x], rson[last], mid+1, r, val, v);
}
ll query(int x, int l, int r, int k)
{
    if(k > siz[x]) k = siz[x];
    if(l == r) return 1LL * k * b[l];
    int mid = (l + r) >> 1;
    if(k <= siz[lson[x]]) return query(lson[x], l, mid, k);
    else return query(lson[x], l, mid, siz[lson[x]]) + query(rson[x], mid+1, r, k - siz[lson[x]]);
}
int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    int x, y, z, num = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d%d", &x, &y, &z);
        b[i] = z;
        a[++num].x = x, a[num].p = z, a[num].v = 1;
        a[++num].x = y+1, a[num].p = -z, a[num].v = -1;
    }
    sort(b + 1, b + 1 + n);
    int len = unique(b + 1, b + 1 + n) - b - 1;
    for(int i = 1; i <= num; i += 2)
    {
        a[i].tp = lower_bound(b + 1, b + 1 + len, a[i].p) - b;
        a[i+1].tp = a[i].tp;
    }
    sort(a + 1, a + 1 + num, cmp);
    int j = 1;
    for(int i = 1; i <= m; i++)
    {
        root[i] = root[i-1];
        while(a[j].x == i) update(root[i], root[i], 1, len, a[j].tp, a[j].v), j++;
    }
    ll ans = 1;
    for(int i = 1; i <= m; i++)
    {
        int x, a, b, c;
        scanf("%d%d%d%d", &x, &a, &b, &c);
        int k = 1 + (a * ans + b) % c;
        ans = query(root[x], 1, len, k);
        printf("%lld\n", ans);
    }
    return 0;
}
發佈了601 篇原創文章 · 獲贊 25 · 訪問量 24萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章