[CQOI2015]任务查询系统(主席树)

[CQOI2015]任务查询系统(luogu)

Description

题目描述

最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分。

超级计算机中的任务用三元组 (s_i,e_i,p_i) 描述,(s_i,e_i,p_i) 表示任务从第 s_ii 秒开始,

在第 e_i 秒后结束(第 s_i 秒和 e_i 秒任务也在运行),其优先级为 p_i。同一时间可能有多个任务同时执行,

它们的优先级可能相同,也可能不同。调度系统会经常向查询系统询问,第 x_i 秒正在运行的任务中,

优先级最小的 k_i 个任务(即将任务按照优先级从小到大排序后取前 k_i 个)的优先级之和是多少。

特别的,如果 k_i 大于第 x_i秒正在运行的任务总数,则直接回答第 x_​i 秒正在运行的任务优先级之和。

上述所有参数均为整数,时间的范围在 [1,n] 之间。

输入格式

输入文件第一行包含两个空格分开的正整数 m 和 n,分别表示任务总数和时间范围。接下来 m 行,

每行包含三个空格分开的正整数 s_i,e_i,p_i,(siei)描述一个任务。接下来 n 行,

每行包含四个空格分开的整数 x_i,a_i,b_i,c_i描述一次查询。

本题强制在线。

查询的参数 k_i 需要由公式ki=1+(ai×pre+bi)modci 计算得到。
其中 pre 表示上一次查询的结果,定义初始 pre=1 。

Solution
主席树模板???
对于每次开始和结束建一棵主席树,记录每个时间点最后建的一棵树的根编号
然后就是愉快的区间第k大查询模板
好久没这么顺地做一道数据结构啦
Code
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#define ll long long
using namespace std;
const int N=1e5+10;
int n,m,p[N],cnt,tot,x,k,u,v;
ll a,b,c,pre=1;
ll re[N];
struct node
{
    int v,id;
    bool operator <(const node &o)const
    {
        return v<o.v;
    }
}d[N];
vector <int> s[N];
vector <int> t[N];
int rt[N],last;
struct mode
{
    int lc,rc,v;
    ll sum;
}f[N*80];
void build(int l,int r,int &xx,int y,ll r_pos,int dd,int pos)
{
    xx=++tot;
    f[xx]=f[y],f[xx].v+=dd;
    f[xx].sum+=r_pos;
    if(l==r) return ;
    int mid=(l+r)>>1;
    if(pos<=mid) build(l,mid,f[xx].lc,f[y].lc,r_pos,dd,pos);
    else build(mid+1,r,f[xx].rc,f[y].rc,r_pos,dd,pos);
}
ll get(int g,int l,int r,int k)
{
    if(!g) return 0;
    if(f[g].v<=k) return f[g].sum;
    if(l==r) return re[l]*(ll)k;
    int mid=(l+r)>>1;
    if(k<=f[f[g].lc].v) return get(f[g].lc,l,mid,k);
    else return f[f[g].lc].sum+get(f[g].rc,mid+1,r,k-f[f[g].lc].v);
}
int main()
{
    scanf("%d%d",&m,&n);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d%d",&u,&v,&d[i].v),d[i].id=i;
        s[u].push_back(i);
        t[v+1].push_back(i);
    }
    sort(d+1,d+1+m);
    for(int i=1;i<=m;i++)
    {
        if(i==1 || d[i].v!=d[i-1].v) re[++cnt]=d[i].v;
        p[d[i].id]=cnt;
    }
    for(int i=1;i<=n;i++)
    {
        int size=s[i].size();
        for(int j=0;j<size;j++)
            build(1,cnt,rt[i],last,re[p[s[i][j]]],1,p[s[i][j]]),last=rt[i];
        size=t[i].size();
        for(int j=0;j<size;j++)
            build(1,cnt,rt[i],last,-re[p[t[i][j]]],-1,p[t[i][j]]),last=rt[i];
        rt[i]=last;
    }
    while(n--)
    {
        scanf("%d%lld%lld%lld",&x,&a,&b,&c);
        k=1+(a*pre+b)%c;
        pre=get(rt[x],1,cnt,k);
        printf("%lld\n",pre);
    }
    return 0;
}

 

posted @ 2020-02-07 10:37  hsez_cyx  阅读(137)  评论(0)    收藏  举报