• BZOJ3932: [CQOI2015]任务查询系统


      要询问前K小的值之和,并且每个任务都是区间操作,单点修改,为了实现这个操作,我们可以利用差分数组进行实现。。。

      在开始时刻a的位置上,加上任务的优先级,在b+1时刻的位置上,减去任务的优先级,再用主席树维护前缀和。。。然后就没有了

       

    #include<iostream>
    #include<string.h>
    #include<stdio.h>
    #include<algorithm>
    #include<vector>
    #define LL long long
    #define rep(i,j,k) for(int i=j;i<=k;i++)
    #define per(i,j,k) for(int i=j;i>=k;i--)
    #define LL long long
    #define pb push_back
    using namespace std;
    const int N = 2e5+7,M=2e7+7;
    struct node{
      int l,r,sum;
      LL val;
    }tree[M];
    vector<int>v[N];
    int tot,cnt,n,m;
    int root[N],p[N];
    void inserts(int pre,int &now,int l,int r,int val){
        now=++cnt;
        ///更新节点编号
        tree[now]=tree[pre];
        if (val>0)tree[now].sum++;
        ///如果当前是加入新的任务
        else tree[now].sum--;
        ///如果当前是把任务取消操作
        tree[now].val+=val;
        ///记录一个前缀和
        if(l==r){
            return;
        }
        int mid=(l+r)>>1;
        if(abs(val)<=mid){
            inserts(tree[pre].l,tree[now].l,l,mid,val);
        }else{
            inserts(tree[pre].r,tree[now].r,mid+1,r,val);
        }
    }
    LL query(int rt,int l,int r,int k){
       if (l==r){
          return (LL)l*k;
       }
       int mid=(l+r)>>1;
       ///如果树的左儿子节点的任务个树是大于等于K个,直接查询左子树
       ///反之查询右子树
       if(tree[tree[rt].l].sum>=k){
          return query(tree[rt].l,l,mid,k);
       }else {
          return tree[tree[rt].l].val+query(tree[rt].r,mid+1,r,k-tree[tree[rt].l].sum);
       }
    }
    int main(){
      int a,b,c,mx=0;
      while(~scanf("%d%d",&n,&m)){
          tot=0;
          cnt=0;
          mx=0;
          rep(i,1,n){
              scanf("%d%d%d",&a,&b,&c);
              mx=max(mx,c);
              ///在a时间点上执行+c操作
              v[a].pb(c);
              ///在b+1时间点上执行-c操作
              v[b+1].pb(-c);
              ///v其实存储的就是每个时间点的操作
          };
          rep(i,1,n){
             for(int j=v[i].size()-1;j>=0;j--){
                tot++;
                inserts(root[tot-1],root[tot],1,mx,v[i][j]);///需要把每个时间点的操作进行更新
             }
             p[i]=tot;///每个时间点处理完成后,那么最后编号才是树根
          }
          int x;
          LL las=1,K;
          while(m--)
          {
              scanf("%d%d%d%d",&x,&a,&b,&c);
              x=root[p[x]];
              K=1+(las*a+b)%c;
              ///如果里面的个数不足K个
              if(tree[x].sum<=K){
                  printf("%lld
    ",tree[x].val);
                  las=tree[x].val;
              }else{
                  las=query(x,1,mx,K);
                  printf("%lld
    ",las);
              }
          }
      }
      return 0;
    }
    有不懂欢迎咨询 QQ:1326487164(添加时记得备注)
  • 相关阅读:
    plaidctf2015 uncorrupt png
    Tsinghua dsa pa2
    课上实验-小软件破解
    HBase Block Cache(块缓存)
    JVM垃圾回收(二)- Minor GC vs Major GC vs Full GC
    JVM垃圾回收(一)- 什么是垃圾回收
    HBase Region 各个状态的转换
    HBase架构
    用GraphX分析伴生网络(二)
    用GraphX分析伴生网络(一)
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11348314.html
Copyright © 2020-2023  润新知