定一个含有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-i+1),并且,你可以改变一些a[i]的值,改变后,程序还能针对改变后的a继续回答上面的问题。你需要编一个这样的程序,从输入文件中读入序列a,然后读入一系列的指令,包括询问指令和修改指令。对于每一个询问指令,你必须输出正确的回答。 第一行有两个正整数n(1≤n≤10000),m(1≤m≤10000)。分别表示序列的长度和指令的个数。第二行有n个数,表示a[1],a[2]……a[n],这些数都小于10^9。接下来的m行描述每条指令,每行的格式是下面两种格式中的一种。 Q i j k 或者 C i t Q i j k (i,j,k是数字,1≤i≤j≤n, 1≤k≤j-i+1)表示询问指令,询问a[i],a[i+1]……a[j]中第k小的数。C i t (1≤i≤n,0≤t≤10^9)表示把a[i]改变成为t。

写了一个树状数组套主席树的做法 nlog^2n, 还有一个节省空间但是耗时间的算法是线段树套平衡树,nlog^3n

沉迷数据结构

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 2000000
#define MM 10000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
}
char op[];
int rt[MM*+],n,m,cnt,tot,l2[MM*+],s[MM+],c[],cnum,b[],bnum;
struct Segment_Tree{
int l,r,x;
}T[MN+];
struct ques{
int kind,l,r,v;
}q[MM+]; void ins(int x,int v,int ad,int l=,int r=tot)
{
T[x].x+=ad;
if(l==r) return;
int mid=l+r>>;
if(v<=mid) ins(T[x].l?T[x].l:(T[x].l=++cnt),v,ad,l,mid);
else ins(T[x].r?T[x].r:(T[x].r=++cnt),v,ad,mid+,r);
} void renew(int x,int v,int ad)
{
for(;x<=tot;x+=x&(-x))
ins(rt[x],v,ad);
} int main()
{
tot=n=read();m=read();
for(int i=;i<=n;i++) l2[i]=s[i]=read();
for(int i=;i<=m;i++)
{
scanf("%s",op);q[i].l=read();
q[i].r=read();
if(op[]=='Q') q[i].kind=,q[i].v=read();
else q[i].kind=,l2[++tot]=q[i].r;
}
sort(l2+,l2+tot+);
for(int i=;i<=tot;i++) rt[i]=i;cnt=tot;
for(int i=;i<=n;i++)
{
s[i]=lower_bound(l2+,l2+tot+,s[i])-l2;
renew(i,s[i],);
}
for(int i=;i<=m;i++)
{
if(q[i].kind==)
{
q[i].r=lower_bound(l2+,l2+tot+,q[i].r)-l2;
renew(q[i].l,s[q[i].l],-);
renew(q[i].l,q[i].r,);
s[q[i].l]=q[i].r;
}
else
{
int l=,r=tot,mid;cnum=bnum=;
for(int j=q[i].r;j;j-=j&(-j))c[++cnum]=rt[j];
for(int j=q[i].l-;j;j-=j&(-j)) b[++bnum]=rt[j];
while(l<=r)
{
mid=l+r>>;int x=;
for(int j=;j<=cnum;j++) x+=T[T[c[j]].l].x;
for(int j=;j<=bnum;j++) x-=T[T[b[j]].l].x;
if(x>=q[i].v)
{
r=mid;
for(int j=;j<=cnum;j++) c[j]=T[c[j]].l;
for(int j=;j<=bnum;j++) b[j]=T[b[j]].l;
}
else
{
l=mid+;q[i].v-=x;
for(int j=;j<=cnum;j++) c[j]=T[c[j]].r;
for(int j=;j<=bnum;j++) b[j]=T[b[j]].r;
}
}
printf("%d\n",l2[r]);
}
}
return ;
}

线段树套平衡树  结果我一不小心写成了树状数组  空间nlogn 时间nlog^3n

一开始把重建操作注释掉了交上去居然也过了,BST最棒啦,垃圾替罪羊

#include<iostream>
#include<cstdio>
#include<algorithm>
#define MN 400000
#define MM 10000
using namespace std;
inline int read()
{
int x = , f = ; char ch = getchar();
while(ch < '' || ch > ''){ if(ch == '-') f = -; ch = getchar();}
while(ch >= '' && ch <= ''){x = x * + ch - '';ch = getchar();}
return x * f;
}
char op[];
int rt[MM*+],n,m,cnt,mark=,tot,top=,l2[MM*+],s[MM+];
int c[MN+][],size[MN+],num[MN+],nn[MN+],fa[MN+],qx[MN+];
struct ques{
int kind,l,r,v;
}q[MM+]; void ins(int&x,int v,int ad,int last)
{
//cout<<"ins"<<x<<" "<<v<<" "<<ad<<" "<<last<<endl;
if(!x){x=++cnt;nn[x]=v;num[x]=;size[x]=;fa[x]=last;return;}
if(v==nn[x]){num[x]+=ad;size[x]+=ad;return;}
if(v<nn[x]) ins(c[x][],v,ad,x);
else ins(c[x][],v,ad,x);
size[x]=size[c[x][]]+size[c[x][]]+num[x];
if(max(size[c[x][]],size[c[x][]])>=0.7*size[x]) mark=x;
} void dfs(int x)
{
if(c[x][]) dfs(c[x][]);
if(num[x])qx[++top]=x;
if(c[x][]) dfs(c[x][]);
fa[x]=c[x][]=c[x][]=;
} void build(int&x,int l,int r,int last)
{
if(l>r) {x=;return;}int mid=l+r>>;
x=qx[mid];fa[x]=last;
build(c[x][],l,mid-,x);
build(c[x][],mid+,r,x);
size[x]=size[c[x][]]+size[c[x][]]+num[x];
} void rebuild(int i)
{
top=;int y=fa[mark];dfs(mark);
if(!y) build(rt[i],,top,);
else build(c[y][c[y][]==mark],,top,y);
mark=;
} void renew(int x,int v,int ad)
{
for(;x<=tot;x+=x&(-x))
{
ins(rt[x],v,ad,);
if(mark) rebuild(x);
}
} int query(int x,int k)
{
if(!x) return ;
if(nn[x]>=k) return query(c[x][],k)+((nn[x]==k)?num[x]:);
else return size[c[x][]]+num[x]+query(c[x][],k);
} int check(int x,int v)
{
int sum=;
for(;x;x-=x&(-x))
sum+=query(rt[x],v);
return sum;
} int main()
{
tot=n=read();m=read();
for(int i=;i<=n;i++) l2[i]=s[i]=read();
for(int i=;i<=m;i++)
{
scanf("%s",op);q[i].l=read();
q[i].r=read();
if(op[]=='Q') q[i].kind=,q[i].v=read();
else q[i].kind=,l2[++tot]=q[i].r;
}
sort(l2+,l2+tot+);
for(int i=;i<=n;i++)
{
s[i]=lower_bound(l2+,l2+tot+,s[i])-l2;
renew(i,s[i],);
}
for(int i=;i<=m;i++)
{
if(q[i].kind==)
{
q[i].r=lower_bound(l2+,l2+tot+,q[i].r)-l2;
renew(q[i].l,s[q[i].l],-);
renew(q[i].l,q[i].r,);
s[q[i].l]=q[i].r;
}
else
{
int l=,r=tot,mid,ans=;
while(l<=r)
{
mid=l+r>>;
int x=check(q[i].r,mid)-check(q[i].l-,mid);
//cout<<l2[mid]<<" "<<check(q[i].r,mid)<<" "<<check(q[i].l-1,mid)<<endl;
if(x>=q[i].v) ans=mid,r=mid-;
else l=mid+;
}
printf("%d\n",l2[ans]);
}
}
return ;
}

[bzoj1901]动态区间k大的更多相关文章

  1. zoj 2112 Dynamic Rankings 动态第k大 线段树套Treap

    Dynamic Rankings Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.zju.edu.cn/onlinejudge/show ...

  2. ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  3. poj2104 划分树 区间K大 在线 无修改

    博主sbit....对于高级数据结构深感无力,然后这些东西在OI竟然烂大街了,不搞就整个人都不好了呢. 于是我勇猛的跳进了这个大坑 ——sbit 区间K大的裸题,在线,无修改. 可以用归并树(\(O( ...

  4. zoj2112 主席树动态第k大 (主席树&&树状数组)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  5. POJ 2104 K-th Number ( 求取区间 K 大值 || 主席树 || 离线线段树)

    题意 : 给出一个含有 N 个数的序列,然后有 M 次问询,每次问询包含 ( L, R, K ) 要求你给出 L 到 R 这个区间的第 K 大是几 分析 : 求取区间 K 大值是个经典的问题,可以使用 ...

  6. 动态求区间K大值(权值线段树)

    我们知道我们可以通过主席树来维护静态区间第K大值.我们又知道主席树满足可加性,所以我们可以用树状数组来维护主席树,树状数组的每一个节点都可以开一颗主席树,然后一起做. 我们注意到树状数组的每一棵树都和 ...

  7. zoj 2112 Dynamic Rankings(主席树&amp;动态第k大)

    Dynamic Rankings Time Limit: 10 Seconds      Memory Limit: 32768 KB The Company Dynamic Rankings has ...

  8. poj2104 主席树 区间K大 在线 无修改

    关于主席树: 主席树(Chairman Tree)是一种离线数据结构,使用函数式线段树维护每一时刻离散之后的数字出现的次数,由于各历史版本的线段树结构一致,可以相减得出区间信息,即该区间内出现的数字和 ...

  9. [BZOJ 1112] [POI2008] 砖块Klo 【区间K大】

    题目链接:BZOJ - 1112 题目分析 枚举每一个长度为k的连续区间,求出这个区间的最优答案,更新全局答案. 可以发现,这个区间的所有柱子最终都变成这k个数的中位数时最优,那么我们就需要查询这个区 ...

随机推荐

  1. DOM相关知识

    一.查找元素 间接查找 parentNode // 父节点 childNodes // 所有子节点 firstChild // 第一个子节点 lastChild // 最后一个子节点 nextSibl ...

  2. DML数据操作语言之常用函数

    所谓函数,就是输入某一值,得到相应的输出结果的功能.相当于一个加工厂,给了原料,最终产出成品. 其中原料 就是参数(parameter). 产品 就是返回值. 函数大致可以分为以下五个种类: 算术函数 ...

  3. 2017 清北济南考前刷题Day 3 morning

    实际得分:100+0+0=100 T1 右上角是必败态,然后推下去 发现同行全是必胜态或全是必败态,不同行必胜必败交叉 列同行 所以n,m 只要有一个是偶数,先手必胜 #include<cstd ...

  4. VMware虚拟机误删除vmdk文件后如何恢复?

    故障描述: Dell R710系列服务器(用于VMware虚拟主机),Dell MD 3200系列存储(用于存放虚拟机文件),VMware ESXi 5.5版本,因意外断电,导致某台虚拟机不能正常启动 ...

  5. MSSQL 2000 错误823恢复

    一.故障描述 MSSQL Server 2000 附加数据库错误823,附加数据库失败.数据库没有备份,不能通过备份恢复数据库,急需恢复数据库中的数据. 二.故障分析SQL Server数据库 823 ...

  6. Huginn实现自动通过slack推送豆瓣高分电影

    博客搬迁至https://blog.wangjiegulu.com RSS订阅:https://blog.wangjiegulu.com/feed.xml 原文链接:https://blog.wang ...

  7. bootstrap的ajax提交

    一般后台界面都用bootstrap框架,这是一个css框架,里面封装了ajax方法,只需要在样式中指定就行,根本自己不用写 <td> <eq name='item.status' v ...

  8. it's a big trick

    今天,正式的登上了我注册已久的博客园,最初注册园子得出发点是记录生活点滴和学习工作的心得的,那就不忘初心,从头开始吧. 从校园到工作,从东北到南方 我们毕业啦 谁说毕业遥遥无期,转眼就要各奔东西. 是 ...

  9. 记录Yii2代码调试中出现的两个问题(截图展示)

    1.代码会中断执行,不提示错误信息,是由于substr函数第一个参数为数组造成的 2. 谷歌浏览器调试异步调用接口时出现的错误,需在接口返回处进行断点调试 这两个错误比较隐蔽,调试代码时必须认真仔细

  10. OAuth2.0学习(2-1)Spring Security OAuth2.0 开发指南

    开发指南:http://www.cnblogs.com/xingxueliao/p/5911292.html Spring OAuth2.0 提供者实现原理: Spring OAuth2.0提供者实际 ...