BZOJ3932:[CQOI2015]任务查询系统——题解

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

题面源于洛谷

题目描述

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

输入输出格式

输入格式:

输入文件第一行包含两个空格分开的正整数m和n,分别表示任务总数和时间范围。接下来m行,每行包含三个空格分开的正整数Si、Ei和Pi(Si<=Ei),描述一个任务。接下来n行,每行包含四个空格分开的整数Xi、Ai、Bi和Ci,描述一次查询。查询的参数Ki需要由公式 Ki=1+(Ai*Pre+Bi) mod Ci计算得到。其中Pre表示上一次查询的结果,对于第一次查询,Pre=1。

输出格式:

输出共n行,每行一个整数,表示查询结果。

输入输出样例

输入样例#1:

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

输出样例#1:

2
8
11

————————————————————————

抄代码一时爽,事后比较火葬场。

查了半个小时发现两个语句反了(晕……

代码于:http://blog.csdn.net/oakley_/article/details/52250622 理解于:http://blog.csdn.net/shiyukun1998/article/details/44910169

!注意!请不要hack我的程序,我知道我抄的代码以及那篇博客的代码的空间复杂度不对,一个主席树的空间复杂度为O(nlogn)级别的,如果不离散化的话是绝对会炸的,所以能过……只能说数据水吧。

我们根据某矩形覆盖的题,想到能否看做在s时刻插入p,在e+1时刻删除p。

那么按照某矩形覆盖的想法,我们分为上下边界,上边界存p,下边界存-p。

根据他们插入/删除的时间排序,之后我们就可以愉快的在p的范围区间内建主席树啦!

Q1:等等,怎么突然就跳到主席树啦?

A1:那这里说一下主席树的想法:在一棵当前时间的主席树上查找区间前k小的数,然后加和即可。!注意!可能有多个任务重合在一个地点上,所以不要忘了加上。

Q2:别忽悠我,只有一棵树的话你岂不是要把前面时间的数也算在内?

A2:是这样的没错,但是因为前面时间的值已经被我们的下边界减掉了,同时于他们的sum和size,所以区间第k小不会搜到他们。

Q3:你的意思是……求k前缀和?

A3:我的理解是这样,但是我的代码实现能力太糟糕了,没有这样写过,很抱歉。

Q4:代码怎么这么不清真?

A4:实在是处于主席树开荒期,所以不可避免的借鉴他人思路,有些时候相比较看题解而言看他们的代码更为清楚一些。

#include<cstdio>
#include<queue>
#include<cctype>
#include<cstring>
#include<cmath>
#include<vector>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=200010;
inline int read(){
    int X=0,w=0;char ch=0;
    while(!isdigit(ch)){w|=ch==‘-‘;ch=getchar();}
    while(isdigit(ch))X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    return w?-X:X;
}
struct mission{
    int pos;
    ll p;
}scp[N];
inline bool cmp(mission a,mission b){
    return a.pos<b.pos;
}
struct tree{
    int l;
    int r;
    int size;
    ll sum;
}tr[10000001];
int rt[N],to[N],n,q,pool;
ll m;
inline void insert(int &y,int &x,int l,int r,ll p){
    tr[x=++pool]=tr[y];
    if(l==r){
        if(p>0)tr[x].size++;
        else tr[x].size--;
        tr[x].sum+=p;
        return;
    }
    int mid=(l+r)>>1;
    if(abs(p)<=mid)insert(tr[y].l,tr[x].l,l,mid,p);
    else insert(tr[y].r,tr[x].r,mid+1,r,p);
    tr[x].sum=tr[tr[x].l].sum+tr[tr[x].r].sum;
    tr[x].size=tr[tr[x].l].size+tr[tr[x].r].size;
    return;
}
ll check(ll H,ll k){
    ll x=rt[H],l=1,r=m,ans=0;
    if(tr[x].size<=k){
        return tr[x].sum;
    }
    while(l<r){
        ll mid=(l+r)>>1;
        if(tr[tr[x].l].size>=k){
            r=mid;
            x=tr[x].l;
        }else{
            l=mid+1;
            k-=tr[tr[x].l].size;
            ans+=tr[tr[x].l].sum;
            x=tr[x].r;
        }
    }
    if(k)ans+=l*k;
    return ans;
}
int main(){
    n=read();
    q=read();
    n*=2;
    for(int i=1;i<=n;i+=2){
        scp[i].pos=read();
        scp[i+1].pos=read()+1;
        scp[i].p=read();
        scp[i+1].p=-scp[i].p;
        m=max(m,scp[i].p);
    }
    sort(scp+1,scp+n+1,cmp);
    for(int i=1;i<=n;i++)insert(rt[i-1],rt[i],1,m,scp[i].p);
    for(int i=n;i>=1;i--)if(scp[i].pos!=scp[i+1].pos)to[scp[i].pos]=i;
    for(int i=1;i<=n>>1;i++)if(!to[i])to[i]=to[i-1];
    ll pre=1;
    for(int i=1;i<=q;i++){
        int X=read();
        ll A=read();
        ll B=read();
        ll C=read();
        ll K=1+(A%C*pre%C+B%C)%C;
        printf("%lld\n",pre=check(to[X],K));
    }
    return 0;
}

原文地址:https://www.cnblogs.com/luyouqi233/p/8151464.html

时间: 2024-10-08 07:20:50

BZOJ3932:[CQOI2015]任务查询系统——题解的相关文章

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

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

[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,眼查,无果,跟踪,无果. 拍了几组小数

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

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

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】 CQOI2015—任务查询系统

http://www.lydsy.com/JudgeOnline/problem.php?id=3932 (题目链接) 题意 给出$m$个区间,每个区间有一个权值,$n$组询问,每次询问在位置$x$权值前$k$大的区间的权值和. Solution 扫描线搞一下然后主席树维护即可. 细节 查询的时候注意叶子节的情况 代码 // bzoj3932 #include<algorithm> #include<iostream> #include<cstdlib> #includ

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

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

bzoj 3932: [CQOI2015]任务查询系统

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

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

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