zoukankan      html  css  js  c++  java
  • 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(添加时记得备注)
  • 相关阅读:
    python3编写网络爬虫18-代理池的维护
    python3编写网络爬虫17-验证码识别
    python3编写网络爬虫16-使用selenium 爬取淘宝商品信息
    python3编写网络爬虫15-Splash的使用
    python3编写网络爬虫14-动态渲染页面爬取
    LeetCode959 由斜杠划分区域(Java并查集)
    编译原理--语法分析之LR分析法的简单实现
    VsCode背景图片设置
    编译原理--基于Lex的词法分析器实验
    HDFS常用的shell命令
  • 原文地址:https://www.cnblogs.com/bluefly-hrbust/p/11348314.html
Copyright © 2011-2022 走看看