• [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
    ",res=seg[rt[x]].sum);
            else printf("%lld
    ",res=Query(rt[x],k,1,tot));
        }
        return 0;
    }
  • 相关阅读:
    http://caibaojian.com/jquery/ JQuery在线查询手册
    验证码
    显式提交/隐式提交 //ajax方式的隐式提交
    事物 银行转账业务
    模板 Template
    登录页面跳转与错误提示信息
    连接池 八种基本类型
    文件,文件夹的基本操作--------数据流的传输
    vim编辑器
    Linux中创建和使用静态库&动态库
  • 原文地址:https://www.cnblogs.com/newera/p/9363015.html
Copyright © 2020-2023  润新知