题目链接:点击查看

题目大意:给出一个长度为 n 的数列 a,再给出 m 次操作:

  1. Q l r k:返回区间 [ l , r ] 内第 k 大的数
  2. C x y:令 a[ x ] = y

题目分析:其实就是带修主席树。。考虑静态主席树,维护的是一个线段树的前缀和,如果强行修改的话,修改一次的最坏时间复杂度将高达 nlogn,完成 m 次操作后的时间复杂度为 nmlogn,还不如直接暴力去区间里找呢。。直接暴力的话时间复杂度也才 n * m

所以为了尽可能去平衡查询和修改的时间复杂度,考虑用树状数组维护前缀和,树状数组维护普通数组的前缀和,只需要维护 lowbit 位置的 logn 个点,将数组换成主席树,也就只需要维护 logn 条链即可,这样查询和修改的时间复杂度都是 nlog^2n

注意,时空复杂度都是 nlog^2n,所以主席树的空间应该开 1e5 * log( 1e5 ) * log( 1e5 ) ≈ 400N,本来是想直接开 1e5 * log( 1e5 ) * log( 1e9 ) 的,这样就不用离散化了,可惜空间不太够用,所以只能去离线然后乖乖离散化了

代码:

//#pragma GCC optimize(2)
//#pragma GCC optimize("Ofast","inline","-ffast-math")
//#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<iostream>
#include<cstdio>
#include<string>
#include<ctime>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<stack>
#include<climits>
#include<queue>
#include<map>
#include<set>
#include<sstream>
#include<cassert>
#include<bitset>
#include<unordered_map>
using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=1e5+100;struct Qu
{char op[5];int a,b,c;
}q[N];int a[N],n,m,len;struct Node
{int l,r;int sum;
}tree[N*640];int cnt,root[N],num[2],temp[2][20];int lowbit(int x)
{return x&(-x);
}void update(int num,int &k,int l,int r,int val)
{tree[cnt++]=tree[k];k=cnt-1;tree[k].sum+=val;if(l==r)return;int mid=l+r>>1;if(num<=mid)update(num,tree[k].l,l,mid,val);elseupdate(num,tree[k].r,mid+1,r,val);
}void add(int pos,int val)
{for(int i=pos;i<=n;i+=lowbit(i))update(a[pos],root[i],1,len,val);
}int query(int l,int r,int k)
{if(l==r)return l;int sum=0;for(int i=1;i<=num[1];i++)sum+=tree[tree[temp[1][i]].l].sum;for(int i=1;i<=num[0];i++)sum-=tree[tree[temp[0][i]].l].sum;int mid=l+r>>1;if(k<=sum){for(int i=1;i<=num[1];i++)temp[1][i]=tree[temp[1][i]].l;for(int i=1;i<=num[0];i++)temp[0][i]=tree[temp[0][i]].l;return query(l,mid,k);}else{for(int i=1;i<=num[1];i++)temp[1][i]=tree[temp[1][i]].r;for(int i=1;i<=num[0];i++)temp[0][i]=tree[temp[0][i]].r;return query(mid+1,r,k-sum);}
}int ask(int l,int r,int k)
{num[0]=num[1]=0;for(int i=l-1;i>0;i-=lowbit(i))temp[0][++num[0]]=root[i];for(int i=r;i>0;i-=lowbit(i))temp[1][++num[1]]=root[i];return query(1,len,k);
}vector<int>node;int get_id(int x)
{return lower_bound(node.begin(),node.end(),x)-node.begin()+1;
}void discreate()
{sort(node.begin(),node.end());node.erase(unique(node.begin(),node.end()),node.end());len=node.size();for(int i=1;i<=n;i++)a[i]=get_id(a[i]);for(int i=1;i<=m;i++)if(q[i].op[0]=='C')q[i].b=get_id(q[i].b);
}void init()
{root[0]=0;tree[0].l=tree[0].r=tree[0].sum=0;cnt=1;
}int main()
{
#ifndef ONLINE_JUDGE
//  freopen("data.in.txt","r",stdin);
//  freopen("data.out.txt","w",stdout);
#endif
//  ios::sync_with_stdio(false);init();scanf("%d%d",&n,&m);for(int i=1;i<=n;i++){scanf("%d",a+i);node.push_back(a[i]);}for(int i=1;i<=m;i++){scanf("%s",q[i].op);if(q[i].op[0]=='C'){scanf("%d%d",&q[i].a,&q[i].b);node.push_back(q[i].b);}elsescanf("%d%d%d",&q[i].a,&q[i].b,&q[i].c); }discreate();for(int i=1;i<=n;i++)add(i,1);  for(int i=1;i<=m;i++){if(q[i].op[0]=='Q'){printf("%d\n",node[ask(q[i].a,q[i].b,q[i].c)-1]);}else{add(q[i].a,-1);a[q[i].a]=q[i].b;add(q[i].a,1);}}return 0;
}

洛谷 - P2617 Dynamic Rankings(树状数组套主席树)相关推荐

  1. 【BZOJ1901】Dynamic Rankings,树状数组套主席树

    Time:2016.05.09 Author:xiaoyimi 转载注明出处谢谢 传送门(权限) 题面 1901: Zju2112 Dynamic Rankings Time Limit: 10 Se ...

  2. H - Hello Ms. Ze(树状数组套主席树,线段树上二分)

    H - Hello Ms. Ze 给定nnn种不同的材料,第iii种材料有aia_iai​个,有mmm个操作,操作分为两类: 把第xxx种材料修改为yyy个, 只用[l,r][l, r][l,r]区间 ...

  3. ICPC 徐州 H Yuuki and a problem (树状数组套主席树)

    Yuuki and a problem 先不管第一问的修改操作,考虑如何达到第二问的查询操作, 题目要我们给出一个区间[l,r][l, r][l,r]中,不能通过权值+++得到的最小的数字是什么, 假 ...

  4. #279. [SYZOI Round1] 滑稽♂树(树状数组套主席树)

    #279. [SYZOI Round1] 滑稽♂树 子树上的问题,考虑dfsdfsdfs序,第kkk大,可以用主席树嘛,支持修改,那就树状数组上套主席树,参考P4175 [CTSC2008]网络管理( ...

  5. zoj 2112 树状数组 套主席树 动态求区间 第k个数

    总算是把动态求区间第k个数的算法看明白了. 在主席树的基础上,如果有修改操作,则要通过套树状数组来实现任意区间求第k小的问题. 刚开始看不明白什么意思,现在有一点理解.树状数组的每个元素是一个线段树, ...

  6. 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)

    http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...

  7. BZOJ1146[CTSC2008]网络管理——出栈入栈序+树状数组套主席树

    题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个 部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条 ...

  8. BZOJ1901Zju2112 Dynamic Rankings——树状数组套主席树

    题目描述 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1 ],a[i+2]--a[j]中第k小的数是多少(1≤k ...

  9. BZOJ1901 Zju2112 Dynamic Rankings 【树状数组套主席树】

    题目 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[j]中第k小的数是多少(1≤k≤j- ...

最新文章

  1. 基片集成波导原理_图解分析:华为1:8 PLC分光器及石英基板集成波导光功率分配器...
  2. 怎么去掉Xcode工程中的某种类型的警告
  3. SAP UI5 初学者教程之二十一 - SAP UI5 的自定义格式器(Custom Formatter) 试读版
  4. 腾讯砸1亿斗地主欢乐豆签约前《英雄联盟》电竞职业选手Uzi
  5. 【java】创建一个线程,可以对其名称进行设置
  6. h5实现一键复制到粘贴板 兼容iOS
  7. jsp 页面之${fn:}内置函数列表
  8. paip.输入法编程---带ord gudin去重复-
  9. sql删除表中各类重复数据
  10. 【JavaScript】封装对象与强制类型转换
  11. Python爬取新浪足球数据(以中超为例)
  12. 爷回青——小米5s Plus刷入LineageOS
  13. 【数据库查询表结构】
  14. SQLite3 dll加载失败问题解决
  15. 科研ABC - SCI论文写作
  16. 架构基础 - WAL在各种数据系统的应用
  17. 谷歌PR权重劫持的原理与方法介绍
  18. 也许事情本身的意义,没你想的那么重要。
  19. 绘制原理图时的常识(一)Stm32F103ZE电源供电
  20. 【文件】VFS四大struct:file、dentry、inode、super_block 是什么?区别?关系?--编辑中...

热门文章

  1. html中怎样调用xml,HTML中调用XML数据实例
  2. 怎么写脚本_直播脚本怎么写|请收下这份攻略
  3. explain 之 id
  4. 防重 Token 令牌如何实现幂等性?
  5. 使用Zookeeper实现leader选举
  6. JMM如何解决顺序一致性问题-JMM层面的内存屏障
  7. 高仿真的类-DefaultListableBeanFactory
  8. 引入了一个IO多路复用模型
  9. base64补等号规则说明
  10. Ant Design入门之开始使用