1 条题解

  • 0
    @ 2025-8-24 21:46:02

    自动搬运

    查看原文

    来自洛谷,原作者为

    avatar xudaxia
    **

    搬运于2025-08-24 21:46:02,当前版本为作者最后更新于2018-12-31 08:23:07,作者可能在搬运后再次修改,您可在原文处查看最新版

    自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多

    以下是正文


    [CQOI2015]任务查询系统

    一开始受到HNOI2015摘果子的启发写了一发树套树,然后就T了

    这题要求求覆盖一个点的前k小区间和。强制在线。

    但主席树的解法其实差不多,因为主席树有前缀和的思想,我们把每一个区间拆开,在ll处加区间的权值,在r+1r+1处减区间的权值,然后用主席树维护一个前缀和。
    我们就可以单点查询了。在主席树上二分就行了。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    using namespace std;
    const int N=1e5+10;
    int read(){
        int sum=0,f=1;char ch=getchar();
        while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
        while(ch>='0'&&ch<='9'){sum=sum*10+ch-'0';ch=getchar();}
        return sum*f;
    }
    int n,m,num,tot;
    int a[N],b[N],root[N<<6];
    long long ans=1;
    struct tree {
        long long sum; 
        int cnt,l,r;
    }t[N<<6];
    vector<int>be[N],ed[N];
    void update(int &u,int l,int r,int pre,int pos,int v){
        u=++tot; t[u]=t[pre];
        t[u].cnt+=v, t[u].sum+=1ll*v*b[pos];
        if(l==r) return;
        int mid=(l+r)>>1;
        if(pos<=mid) update(t[u].l,l,mid,t[pre].l,pos,v);
        else update(t[u].r,mid+1,r,t[pre].r,pos,v);
    }
    long long query(int u,int l,int r,int k){
        int num=t[t[u].l].cnt;
        if(l==r) return t[u].sum/(1ll*t[u].cnt)*1ll*k;
        int mid=(l+r)>>1;
        if(k<=num) return query(t[u].l,l,mid,k);
        else return query(t[u].r,mid+1,r,k-num)+t[t[u].l].sum;
    }
    int main(){
        m=read(),n=read();
        for(int i=1;i<=m;i++) {
            int x=read(),y=read();
            a[i]=read(),b[i]=a[i];
            be[x].push_back(i), ed[y+1].push_back(i);
        }
        sort(b+1,b+1+m); int num=unique(b+1,b+1+m)-b-1;
        for(int i=1;i<=n;i++) {
            root[i]=root[i-1];
            for(int j=0;j<be[i].size();j++) {
                int p=lower_bound(b+1,b+1+num,a[be[i][j]])-b;
                update(root[i],1,num,root[i],p,1);
            }
            for(int j=0;j<ed[i].size();j++) {
                int p=lower_bound(b+1,b+1+num,a[ed[i][j]])-b;
                update(root[i],1,num,root[i],p,-1);
            }
        }
        for(int i=1;i<=n;i++) {
          	int x=read(),a=read(),b=read(),c=read(),k=(1ll*a*ans+b)%c+1;
            if(k>t[root[x]].cnt) ans=t[root[x]].sum;
            else ans=query(root[x],1,num,k);
            printf("%lld\n",ans);
        }
        return 0;
    }
    
    • 1

    信息

    ID
    2241
    时间
    2000ms
    内存
    512MiB
    难度
    6
    标签
    递交数
    0
    已通过
    0
    上传者