动态区间第K小数 分块/树套树
来源:互联网 发布:sql 去重 编辑:程序博客网 时间:2024/05/17 04:30
NKOJ2670 动态区间第K小数
问题描述
给定一个由N个数组成的序列{A1,A2,…,AN}
每次可以将Ak的值改为t,或者提问序列中{Al,..,Ar}中第k小的数的值。
输入格式
第一行两个正整数N,M,表示有N个数,M次操作
接下来每行描述一个操作:
·如果第一个字符时C,那么接下来两个正整数k,t,表示把Ak的值改成t;
·如果第一个字符时Q,那么接下来三个正整数l,r,k,表示提问序列中{Al,..,Ar}中第k小的数的值。
输出格式
对每次提问输出一行,为改次提问的答案。
数据范围
1<=N,M<=50000
初始状态1<=Ak<=50000
每次修改1<=k<=N,1<=t<=50000
每次提问1<=k<=r-l+1
可以用树套树解决,但是编程难度相当大。实际上可以用分块暴力水过。
A数组用来处理C操作,初始就是原序列;用来处理Q操作的的B数组分块之后,把每块中的数进行排序。注意到序列中的数最大只有50000,我们可以对区间第K小数二分答案。如果区间左右端点包含于同一个区间,那么暴力扫一遍判断即可;其他情况下,对于完全覆盖的区间,二分查找该区间比该数小的数有几个,对于两端剩下的区间暴力扫一遍判断比它少的有几个,最后加起来判断即可。
对于C操作,修改后对该区间再排序即可。
最坏情况下,时间复杂度好像是
#include<stdio.h>#include<cmath>#include<algorithm>#define MAXN 50005using namespace std;int N,M,S,A[MAXN],B[MAXN];bool check(int num,int l,int r,int k){ int i,j,x,y,xx,yy,sum=0; x=(l-1)/S+1;xx=x*S; y=(r-1)/S+1;yy=(y-1)*S+1; if(x==y) { for(i=l;i<=r;i++)sum+=A[i]<num; return sum>=k; } for(i=l;i<=xx;i++)sum+=A[i]<num; for(i=yy;i<=r;i++)sum+=A[i]<num; for(i=x+1;i<y;i++)sum+=lower_bound(B+(i-1)*S+1,B+i*S+1,num)-B-((i-1)*S+1); return sum>=k;}int GetAns(int l,int r,int k){ int L=0,R=50001,mid; while(L<R-1) { mid=L+R>>1; if(check(mid,l,r,k))R=mid; else L=mid; } return L;}void Modify(int x,int d){ int i,j,l,r; A[x]=d; j=(x-1)/S+1;l=(j-1)*S+1;r=j*S; if(r>N)r=N; for(i=l;i<=r;i++)B[i]=A[i]; sort(B+l,B+r+1);}int main(){ int i,j,x,y,z; char op[3]; scanf("%d%d",&N,&M); for(i=1;i<=N;i++)scanf("%d",&A[i]),B[i]=A[i]; S=sqrt(N); j=N/S; for(i=1;i<=j;i++)sort(B+(i-1)*S+1,B+i*S+1); if(N%S)sort(B+j*S+1,B+N+1); for(i=1;i<=M;i++) { scanf("%s",op); if(op[0]=='Q') { scanf("%d%d%d",&x,&y,&z); printf("%d\n",GetAns(x,y,z)); } else { scanf("%d%d",&x,&y); Modify(x,y); } }}
阅读全文
0 0
- 动态区间第K小数 分块/树套树
- ZOJ 2112 Dynamic Rankings 动态区间第k大 分块
- 分块 区间第k小
- 区间第k小 分块
- zoj-2112(主席树动态求区间第k小数)
- 区间第K值带修改 分块
- bzoj1901(动态区间第k大,树套树)
- 动态区间第k小 分块 O(nlogn*sqrt(nlogn))
- K小数查询:分块
- 【JZOJ5260】【GDOI2018模拟8.12】区间第k小(分块)
- K小数查询 分块模板
- bzoj 1901 动态区间第k大 (树套树)
- CRB and Queries(动态区间求第k小数模板题:线段树套平衡树)
- pku2140任意区间第k小数-归并树
- ZOJ2112(区间动态求第K大)
- 划分树的学习(求区间第k大的数字)&&分块求区间第k大
- 2017年11月1日提高组 第k小数(二分+分块)
- [JZOJ4438] K小数查询(经典分块)
- React Native 自定义modal
- JAVA 常见的异常
- mybatisy异常 Parameter 'xxx' not found. Available parameters are[1, 0, param1, param2]
- 最新版的struts-2.5.13 配置的时候出现问题和解决方案
- Android JNI开发(2)--native方法调用Java方法
- 动态区间第K小数 分块/树套树
- CSS+HTML实现倾斜导航条
- Shell脚本数组操作小结
- TensorFlow(五)CNN
- Cocos2d-lua 初识shader之三:模糊
- fiddle 本地css/js 替换线上代码调试
- 51 Nod1113 矩阵快速幂
- BeanUtils和Junit的用法
- JAVA学习笔记01——Linux常用命令详解