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

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

Solution

对每个按时间排序,插入到对时间点建以任务优先级为区间的主席树,处理一个记录和的键值,以及一个处理数量的键值就可以做了

注意要开long long,而且空间不能只开n*log2(len)大小的,至少n*60

#include<vector>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iostream>
#include<algorithm>
#define N 100010
#define ll long long
#define INF 10000000
#define mid ((x>>1)+(y>>1)+(x&y&1))
using namespace std;
inline ll Rin(){
    ll x=0,c=getchar(),f=1;
    for(;c<48||c>57;c=getchar())
        if(!(c^45))f=-1;
    for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    return x*f;
}
struct Seg{
    ll sum;
    int sin,ls,rs;
}key[N*60];
vector<int>L[N],R[N];
int n,m,rt[N],tot,mn=INF,mx,sign,mark[N*60];
void newnode(int &pr,int pl){
    key[pr=++tot]=key[pl];
    mark[pr]=sign;
}
void modify(int &pr,int pl,int x,int y,int k,int d){
    if(mark[pl]^sign)
        newnode(pr,pl);
    key[pr].sin+=d;
    key[pr].sum+=k*d;
    if(!(x^y))return;
    if(k<=mid)modify(key[pr].ls,key[pl].ls,x,mid,k,d);
    else modify(key[pr].rs,key[pl].rs,mid+1,y,k,d);
}
ll query(int p,int x,int y,int k){
    if(!(x^y))return (ll)x*k;
    if(key[key[p].ls].sin>=k)return query(key[p].ls,x,mid,k);
    return key[key[p].ls].sum+query(key[p].rs,mid+1,y,k-key[key[p].ls].sin);
}
int main(){
    n=Rin(),m=Rin();
    for(int i=1;i<=n;i++){
        int x=Rin(),y=Rin(),z=Rin();
        L[x].push_back(z);
        R[y].push_back(z);
        mn=min(mn,x);
        mx=max(mx,y);
    }
    for(int i=mn;i<=mx;i++){
        newnode(rt[i],rt[i-1]);sign++;
        for(int j=0;j<L[i].size();j++)
            modify(rt[i],rt[i],1,INF,L[i][j],1);
        for(int j=0;j<R[i-1].size();j++)
            modify(rt[i],rt[i],1,INF,R[i-1][j],-1);
    }
    ll a,b,c,ans=1;
    while(m--){
        int x=Rin();
        a=Rin(),b=Rin(),c=Rin();
        int k=(int)1+(a*ans+b)%c;
        if(key[rt[x]].sin<=k)
            printf("%lld\n",ans=key[rt[x]].sum);
        else
            printf("%lld\n",ans=query(rt[x],1,INF,k));
    }
    return 0;
}
时间: 2024-11-03 01:39:34

[bzoj3932][CQOI2015][任务查询系统] (主席树)的相关文章

bzoj3932 [CQOI2015]任务查询系统——主席树

题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3932 第二道主席树!本来想自己手胡一下,但是还是写不下去了... 参考博客:https://www.cnblogs.com/CQzhangyu/p/6295579.html 就是对每个时间节点建一棵权值线段树,节点太多所以开成主席树: WA了好久,竟然是错在二分的地方了???看了半天还是不知道为什么错,那个写法已经用了好久了啊... 代码如下: #include<iostream> #i

BZOJ 3932: [CQOI2015]任务查询系统 | 主席树练习题

题目: 洛谷也能评测 题解: De了好长时间BUG发现是自己sort前面有一行for没删,气死. 题目询问第x秒时候前k小的P值之和. 朴素想法: 我们可以把P值离散化,然后对于每个时刻建一棵定义域是离散化后P值的线段树 每个节点维护了这个节点代表区间的任务个数和这些任务离散化之前的P值之和, 对于每个在这个时间段的任务,插入,即在p位置单点修改 询问就是类似二叉查找树的写法 高级想法: 首先把一段任务拆成两个:添加和删除,用三元组(t,p,d)表示,d=1表示插入,d=-1表示删除 对于第ma

P3168 [CQOI2015]任务查询系统 主席树 差分数组

现在有一群任务,每个任务都有开始和结束的时间和一个优先级,给你所有任务的开始结束时间和优先级,问你在某个时间点优先级最小的k个的优先级的和是多少. 普通的主席树是单点修改 区间查询   这题正好相反 可以用差分数组来做  区间查询改为1-i的前缀和 注意copy结点的方式 不能简单的复制T  还有son  t num 重复累加的操作  要写成T[i] T[i]      而不是  T[i-1] T[i] 主席树的范围只和放入的数据的离散化下标有关   和历史版本号没有任何关系 这题的时间为历史版

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

版权声明:本文为博主原创文章,未经博主允许不得转载. bzoj 3832 题意: 有一堆任务,每个任务都有一个起始时间和终止时间,外加一个优先级 . 查询第xi秒优先级最小的k任务的优先级的和,如果第xi秒任务数小于k,则输出所有任务的优先级的和 . 解法: 每一秒都建立一颗线段树,线段树记录该时间点每个优先级出现的次数 . 可以把每个任务拆成两部分,一个在某个时间点该优先级次数加1,另一个就是减1了,然后按时间排序,随意搞搞就行了 . code 1 #include <iostream> 2

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

题目描述 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个)的优先级之和是多少.特别的,如果Ki大于第Xi秒正在

[bzoj3932][CQOI2015]任务查询系统-题解[主席树][权值线段树]

Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为Pi.同一时间可能有多个任务同时执行,它们的优先级可能相同,也可能不同.调度系统会经常向 查询系统询问,第Xi秒正在运行的任务中,优先级最小的Ki个任务(即将任务按照优先级从小到大排序后取前Ki个 )的优先级之和是多少.特别的,如

BZOJ3932: [CQOI2015]任务查询系统

传送门 真不知道我没学主席树之前是有什么勇气说自己高级数据结构以及学的七七八八了. 这道题应该也是算是主席树的经典运用. 刚开始脑抽了,想把(S,E,P)的处理直接在线用树状数组xjb搞搞算了.写完后才意识到树状数组无法(很难?)实现区间修改. 然后想了想既然这个是一下子把所有修改都放上了直接用树状数组差分一下不就好了! 然后又深感自己制杖,为什么要用树状数组差分呢,直接开几个vector维护一下就行了. 说是修改,本质上是不带修改的主席树,很快搞完.WA,眼查,无果,跟踪,无果. 拍了几组小数

3932: [CQOI2015]任务查询系统

3932: [CQOI2015]任务查询系统 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 2559  Solved: 819[Submit][Status][Discuss] Description 最近实验室正在为其管理的超级计算机编制一套任务管理系统,而你被安排完成其中的查询部分.超级计算机中的 任务用三元组(Si,Ei,Pi)描述,(Si,Ei,Pi)表示任务从第Si秒开始,在第Ei秒后结束(第Si秒和Ei秒任务也在运行 ),其优先级为P

【BZOJ3932】任务查询系统,主席树与差分的建树思想

Time:2016.05.08 Author:xiaoyimi 转载注明出处谢谢 传送门 思路: 说真的我一开始做这个题真不知道怎么建树,只知道应该以时间为根建树,记录优先值并维护前缀和,但想不出怎么用到主席树的前缀建树思想,暴力建树+修改肯定是不科学的-- 后来去看题解,发现又是差分. 回想起被运输计划支配的恐惧--(还是自己太弱的缘故) 不过这个差分比较简单,因为它正好利用了第i棵主席树以第i-1棵树为基础建树的思路,比如某一任务的时间区间为[l,r],优先度为p,那么我们在root[l]上