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\n",tree[x].val);
              las=tree[x].val;
          }else{
              las=query(x,1,mx,K);
              printf("%lld\n",las);
          }
      }
  }
  return 0;
}

 

posted @ 2019-08-13 20:25  bluefly-hrbust  阅读(144)  评论(0编辑  收藏  举报