题面

分析

对于一个区间修改(s,e,v),我们可以将它差分,这样就变成了单点修改s和e+1(s插入,t+1删除)

我们用主席树维护差分数组的前缀和,第i棵主席树维护区间[1,i]之间的所有差分值

那么查询我们直接在第i棵主席树里查第k大即可

注意:

1.主席树里面要维护两个值,一个是值落在区间[l,r]内的树的个数cnt,一个是这cnt个数的和

2.注意有多个数相同的情况,查询到叶子节点[l,l]之后,不能直接返回sum,而是应该返回k*b[l],其中b[l]是l离散化之前的值

这里有一组hack数据

in:
3 3
1 1 1
1 2 1
1 3 1
1 0 1 100
2 0 1 100
3 0 1 100 rightout:
2
2
1

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#define maxn 300005
#define maxlogn 21
using namespace std;
int m,n;
vector<int>d[maxn];
int b[maxn];
int sz; struct node{
#ifdef DEBUG
int l;
int r;
#endif
int ls;
int rs;
int cnt;
long long sum;
}tree[2*maxn*maxlogn];
int root[maxn*2];
int ptr;
void push_up(int pos){
tree[pos].cnt=tree[tree[pos].ls].cnt+tree[tree[pos].rs].cnt;
tree[pos].sum=tree[tree[pos].ls].sum+tree[tree[pos].rs].sum;
}
void update(int &pos,int last,int upos,int uval,int flag,int l,int r){
pos=++ptr;
tree[pos]=tree[last];
#ifdef DEBUG
tree[pos].l=l;
tree[pos].r=r;
#endif
if(l==r){
tree[pos].cnt+=flag;
tree[pos].sum+=uval*flag;
return;
}
int mid=(l+r)>>1;
if(upos<=mid) update(tree[pos].ls,tree[last].ls,upos,uval,flag,l,mid);
else update(tree[pos].rs,tree[last].rs,upos,uval,flag,mid+1,r);
push_up(pos);
} long long query(int ql,int qr,int qk,int l,int r){
if(l==r){
//注意多组数据相同的情况,必须要用k*值,不能用sum
//见最下方hack数据
return b[l]*qk;
}
int mid=(l+r)>>1;
int lcnt=tree[tree[qr].ls].cnt-tree[tree[ql].ls].cnt;
if(qk<=lcnt) return query(tree[ql].ls,tree[qr].ls,qk,l,mid);
else return tree[tree[qr].ls].sum-tree[tree[ql].ls].sum+query(tree[ql].rs,tree[qr].rs,qk-lcnt,mid+1,r);
} int main(){
int s,e,v;
long long xx,aa,bb,cc;
scanf("%d %d",&m,&n);
for(int i=1;i<=m;i++){
scanf("%d %d %d",&s,&e,&v);
d[s].push_back(v);
d[e+1].push_back(-v);
b[++sz]=v;
}
sort(b+1,b+1+sz);
sz=unique(b+1,b+1+sz)-b-1;
for(int i=1;i<=n;i++){
root[i]=root[i-1];
for(int j=0;j<d[i].size();j++){
int val=d[i][j];//正数代表插入,负数代表删除
int disval=lower_bound(b+1,b+1+sz,abs(val))-b;
if(val<0) update(root[i],root[i],disval,abs(val),-1,1,sz);
else update(root[i],root[i],disval,abs(val),1,1,sz);
}
}
long long ans=1;
for(int i=1;i<=n;i++){
scanf("%lld %lld %lld %lld",&xx,&aa,&bb,&cc);
long long k=1+(aa*ans+bb)%cc;
if(k>tree[root[xx]].cnt) ans=tree[root[xx]].sum;
else ans=query(root[0],root[xx],k,1,sz);
printf("%lld\n",ans);
}
}

最新文章

  1. .Net语言 APP开发平台——Smobiler学习日志:快速实现手机上的图片上传功能
  2. BlogEngine2.9模仿yahoo滚动新闻Widget
  3. Java Map按键(Key)排序和按值(Value)排序
  4. 新建Oracle数据库时,提示使用database control配置数据库时,要求在当前oracle主目录中配置监听程序
  5. awakeFromNib与viewDidLoad的区别
  6. 异步FIFO为什么用格雷码
  7. android 数据库的增删改查的另一种方式
  8. WPF拖动绘制
  9. tomcat thread dump 分析【转载】
  10. C#分层开发MySchool
  11. 实现ModelDriver接口的功能
  12. Product Management vs. Product Marketing
  13. 2017最新PHP初级经典面试题目汇总(下篇)
  14. C#基础知识之类和结构体
  15. I/O模型
  16. js如何获取url参数
  17. 让 Python 更加充分的使用 Sqlite3
  18. d3实现的力向导图
  19. python学习之----Lambda表达式
  20. How to set the bash display to not show the vim text after exit?

热门文章

  1. box-shadow四个边框设置阴影样式
  2. 2018-8-10-使用-Resharper-特性
  3. python 在不同CPU上同时运行多个程序
  4. Xib中用自动布局设置UIScrollView的ContenSize
  5. Windows系统安装教程
  6. zabbix创建钉钉报警
  7. vue框架搭建--axios使用
  8. 如何将word内容粘贴到富文本编辑器里面
  9. 【转】django 正则URL 匹配
  10. [CSP-S模拟测试]:任(duty)(二维前缀和)