【第22期】观点:IT 行业加班,到底有没有价值?

BZOJ 3932 [CQOI2015] 任务查询系统 可持久化线段树

原创 2017年01月03日 21:28:39

题目大意:有n个任务持续m秒,每个任务从si秒开始到ei秒结束且有一个优先级pi,有m个询问,回答第xi秒时正在执行的任务中优先级前k小和,强制在线。

根据时间的变化,任务会开始或结束。我们想知道任一时刻任务的执行情况,这里我们就需要用到可持久化数据结构。对于这道题,我们可以维护一个权值线段树1

可持久化数据结构,暴力地想就是每个版本完全复制一个保存起来,但是空间不够用。
如果每次只是修改一个点的话,在线段树中会有logn个点的信息发生变化,其余仍然和前一秒一样,这样的话直接复用前一秒的版本,空间复杂度从n^2变为nlogn.

具体如何实现呢?
先在第0秒创建一个空版本。把每一个任务分成两个操作:在第si秒插入在ei+1秒删除。把操作按照时间排序然后构建每一秒的权值线段树。插入或删除时要新建结点。

权值范围太大这里需要离散化。
在复制结点的时候不要忘记复制儿子指针。
k要开long long。
线段树查找第k大时递归到点树上要进行讨论。
改了一上午。离散化辣眼睛凑合看吧0.0
UPD 2017/7/1 更新了可读的代码

#include <cstdio>
#include <algorithm>
#include <queue>
#define N 100005
#define INF 1e7
using namespace std;
typedef long long LL;
int n,m,top,b[N];
LL ans=1;
struct Node {
    Node *ch[2];
    int siz;
    LL sum;
    Node() {}
    Node(Node* tmp) {
        if(!tmp) siz=0 , sum=0 , ch[0]=ch[1]=NULL;
        else siz=tmp->siz , sum=tmp->sum , ch[0]=tmp->ch[0] , ch[1]=tmp->ch[1];
    }
    void* operator new(size_t) {
        static Node *mempool,*C;
        if(mempool==C) mempool=(C=new Node[1<<20])+(1<<20);
        return C++;
    }
}*root[N];
void Init(Node*& o,int l,int r) {
    o=new Node(NULL);
    if(l==r) return ;
    int mid=l+r>>1;
    Init(o->ch[0],l,mid); Init(o->ch[1],mid+1,r);
    return ;
}
void Insert(Node*& o,int v,int l,int r) {
    Node* tmp=o;
    o=new Node(tmp);
    int flag=(v>0?1:-1);
    o->siz+=flag , o->sum+=flag*b[abs(v)];
    if(l==r) return ;
    int mid=l+r>>1;
    if(abs(v)<=mid) Insert(o->ch[0],v,l,mid);
    else Insert(o->ch[1],v,mid+1,r);
    return ;
}
LL Query(Node* o,int k,int l,int r) {
    if(k>=o->siz) return o->sum;
    if(l==r) return (o->sum/o->siz)*k;
    int mid=l+r>>1;
    if(o->ch[0]) {
        if(o->ch[0]->siz>=k) return Query(o->ch[0],k,l,mid);
        return o->ch[0]->sum+Query(o->ch[1],k-o->ch[0]->siz,mid+1,r);
    }
    return Query(o->ch[1],k,mid+1,r);
}
struct Operation {
    int ord,val;
    Operation(int x=0,int y=0):ord(x),val(y){}
    bool operator < (const Operation& rhs) const { return ord<rhs.ord; }
    void adjust() {
        int flag=val>0?1:-1;
        val=lower_bound(b+1,b+top+1,abs(val))-b;
        val*=flag;
        return ;
    }
}p[N*2];
int main() {
    scanf("%d%d",&n,&m);
    Init(root[0],1,n);
    for(int i=1,l,r,v;i<=n;i++) {
        scanf("%d%d%d",&l,&r,&v);
        p[i]=Operation(l,v);
        p[i+n]=Operation(r+1,-v);
        b[++top]=v;
    }
    sort(b+1,b+top+1);
    top=unique(b+1,b+top+1)-b-1;
    for(int i=1;i<=2*n;i++) p[i].adjust();
    sort(p+1,p+2*n+1);
    LL k=1;
    for(int i=1;i<=m;i++) {
        root[i]=root[i-1];
        while(p[k].ord==i && k<=n*2) Insert(root[i],p[k++].val,1,n);
    }
    for(int i=1;i<=m;i++) {
        int x,a,b,c;
        scanf("%d%d%d%d",&x,&a,&b,&c);
        k=1+(a*ans+b)%c;
        printf("%lld\n",ans=Query(root[x],k,1,n));
    }
    return 0;
}

  1. 权值线段树是啥?就是结点编号不再代表序列编号,而是权值大小,常在每个结点处维护size域表示当前结点代表的权值范围内有几个数,用于查询第k小。
    第k小怎么查?和Treap差不多啦
版权声明:转载请注明:http://blog.csdn.net/YihAN_Z 举报

相关文章推荐

BZOJ3932 CQOI2015 任务查询系统-可持久化线段树-可持久化平衡树

BZOJ3932 CQOI2015 任务查询系统 1.可持久化线段树 2.可持久化平衡树

Picture(线段树 + 扫描线 + 离散化)

Picture <div class="plm" style="text-align: center; fon

程序员升职加薪指南!还缺一个“证”!

CSDN出品,立即查看!

【BZOJ 3932】[CQOI2015]任务查询系统 主席树

好像真的没什么好说的,主席树维护一个差分就好了。 #include #include #include #include #define maxn 100020 #define LL long lo...

[线段树+离散化]LightOJ 1089 - Points in Segments (II)

题目描述: Givennsegments (1 dimensional) andqpoints, for each point you have to find the number of segments which contain that point. A pointpiwill lie i...

bzoj 3932 [CQOI2015]任务查询系统 可持久化二维线段树

好好的一道主席树被我强行套了一层。。。 然后MLE+TLE,然后我惊奇地发现区间的sum只要开int就行了。。。我的做法: 一个点需要满足si=x,然后求满足这个条件的pi前k小的点的和。 那么...
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)