[BZOJ 3932][CQOI2015]任务查询系统

Link:

BZOJ 3932 传送门

Solution:

一道比较基础的数据结构题吧,然而一开始我想的还是两个$log$……

明显看出我们是要对每一个时刻$x$维护各个权值区间内数的个数及数的和,主席树的经典模型

在一开始建树时可以使用前缀数组差分的方式:

对于任务$(l,r,x)$,修改$<l,x,1>$和$<r+1,x,-1>$之后第$k$点的情况就是其前缀和啦

 

我一开始想的实现方式竟然是两个$log$的带修改主席树……

但实际上由于此题查询时无修改,一开始按照从小到大的顺序依次更新就能直接算出每个点的前缀和

完全没有必要用树状数组套主席树来更新啊……

 

Tip:

1、由于可能要对每个点更新多次,因此每次都以原来的自己为模板新增链

这时要注意$cnt$和$cur$的更新顺序!

2、到达目标值时要注意不能直接返回该点的$sum$

可能该值有多个且取不完,要返回$k*val$!

Code:

#include <bits/stdc++.h>

using namespace std;
const int MAXN=1e5+10;
typedef long long ll;
struct PrTree{int ls,rs,cnt;ll sum;}seg[MAXN*40];
vector<int> S[MAXN],T[MAXN];ll res=1;
int n,m,a,b,c,x,mx,mn=1<<30,rt[MAXN],dsp[MAXN],tot,cnt;

int idx(int x)
{return lower_bound(dsp+1,dsp+tot+1,x)-dsp;}

void Update(int &cur,int pos,int val,int l,int r)
{//由于在自己上增加,要后对cur赋值 
    seg[++cnt]=seg[cur],cur=cnt;
    seg[cur].cnt+=val;seg[cur].sum+=1ll*val*dsp[pos];
    if(l==r) return;int mid=(l+r)>>1;
    if(pos<=mid) Update(seg[cur].ls,pos,val,l,mid);
    else Update(seg[cur].rs,pos,val,mid+1,r);
}

ll Query(int x,int k,int l,int r)
{//注意,不一定全取啊 
    if(l==r) return 1ll*k*dsp[l];
    int mid=(l+r)>>1,t=seg[seg[x].ls].cnt;
    if(k<=t) return Query(seg[x].ls,k,l,mid);
    else return Query(seg[x].rs,k-t,mid+1,r)+seg[seg[x].ls].sum;
}

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d%d%d",&a,&b,&c);
        dsp[i]=c;mn=min(mn,a);mx=max(mx,b+1);
        S[a].push_back(c);T[b+1].push_back(c);
    }
    sort(dsp+1,dsp+n+1);tot=unique(dsp+1,dsp+n+1)-dsp-1;
    
    for(int i=mn;i<=mx;i++)
    {//之后都以自己为模板构造 
        rt[i]=++cnt;seg[rt[i]]=seg[rt[i-1]];
        for(int j=0;j<S[i].size();j++)
            Update(rt[i],idx(S[i][j]),1,1,tot);
        for(int j=0;j<T[i].size();j++)
            Update(rt[i],idx(T[i][j]),-1,1,tot);
    }
    
    while(m--)
    {
        scanf("%d%d%d%d",&x,&a,&b,&c);
        int k=1+(a*res+b)%c;
        if(k>=seg[rt[x]].cnt) printf("%lld\n",res=seg[rt[x]].sum);
        else printf("%lld\n",res=Query(rt[x],k,1,tot));
    }
    return 0;
}

 

posted @ 2018-07-24 22:14  NewErA  阅读(155)  评论(0编辑  收藏  举报