【poj1901-求区间第k大值(带修改)】树状数组套主席树
901: Zju2112 Dynamic Rankings
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 7025 Solved: 2925
[Submit][Status][Discuss]
Description
给定一个含有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。
Input
对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。
Output
Sample Input
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3
Sample Output
6
HINT
20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。
-------------------------------------------------------------------------------------
嗷嗷嗷A了好海森

首先要回忆一下树状数组的样子。。它是一棵树的结构,也就是一个点只会被另一个点所访问到(父亲只有一个)。
上一题不带修改的主席树中,每一棵树是维护前缀区间1~L的。
这样,要是我们要修改一个数的话,就要把后面的主席树全部修改了。。复杂度变成了m*n*logn,这是不能接受的。
然后大神们就想到了树状数组!
我们修改每一棵主席树维护的区间,对于第i棵主席树,维护树状数组中所对应的lowbit(i)个数。
然后修改就只需要m*logn*logn了。
查询则变成了logn*logn的了。
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std; const int N=,INF=(int)1e9+;
int n,m,pl,tl,mx;
int a[*N],num[*N],crt[*N],root[*N];
char s[];
struct trnode{
int lc,rc,cnt;
}t[*N];
struct ques{
int l,r,k,x,d;
bool tmp;
}q[N];
struct node{
int d,id;
}p[*N]; bool cmp(node x,node y){return x.d<y.d;} int bt(int l,int r)
{
int x=++tl;
t[x].cnt=;
t[x].lc=t[x].rc=;
if(l<r)
{
int mid=(l+r)/;
t[x].lc=bt(l,mid);
t[x].rc=bt(mid+,r);
}
return x;
} int update(int rt,int p,int d)
{
int now=++tl,tmp=now;
int l=,r=mx,mid;
t[now].cnt=t[rt].cnt+d;
while(l<r)
{
mid=(l+r)/;
if(p<=mid)
{
r=mid;
t[now].lc=++tl;
t[now].rc=t[rt].rc;
rt=t[rt].lc;
now=tl;
}
else
{
l=mid+;
t[now].lc=t[rt].lc;
t[now].rc=++tl;
rt=t[rt].rc;
now=tl;
}
t[now].cnt=t[rt].cnt+d;
}
return tmp;
} void add(int x,int p,int d)
{
for(int i=x;i<=n;i+=(i&(-i))) root[i]=update(root[i],p,d);
} int getsum(int x)
{
int ans=;
for(int i=x;i>=;i-=(i&(-i))) ans+=t[t[crt[i]].lc].cnt;
return ans;
} int query(int lx,int rx,int k)
{
for(int i=lx-;i>=;i-=(i&(-i))) crt[i]=root[i];//多棵树同时走。
for(int i=rx;i>=;i-=(i&(-i))) crt[i]=root[i];
int l=,r=mx,mid,sum;
while(l<r)
{
mid=(l+r)/;
sum=getsum(rx)-getsum(lx-);
if(sum>=k)
{
r=mid;
for(int i=lx-;i>=;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
for(int i=rx;i>=;i-=(i&(-i))) crt[i]=t[crt[i]].lc;
}
else
{
l=mid+;
k-=sum;
for(int i=lx-;i>=;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
for(int i=rx;i>=;i-=(i&(-i))) crt[i]=t[crt[i]].rc;
}
}
return l;
} int main()
{
freopen("a.in","r",stdin);
scanf("%d%d",&n,&m);
pl=n;tl=;
for(int i=;i<=n;i++)
{
scanf("%d",&a[i]);
p[i].d=a[i];p[i].id=i;
}
for(int i=;i<=m;i++)
{
scanf("%s",s);
if(s[]=='Q')
{
q[i].tmp=;
scanf("%d%d%d",&q[i].l,&q[i].r,&q[i].k);
}
else
{
q[i].tmp=;
scanf("%d%d",&q[i].x,&q[i].d);
p[++pl].d=q[i].d;p[pl].id=n+i;
}
}
sort(p+,p++pl,cmp);
mx=;p[].d=INF;
for(int i=;i<=pl;i++)
{
if(p[i].d!=p[i-].d) mx++,num[mx]=p[i].d;
if(p[i].id<=n) a[p[i].id]=mx;
else q[p[i].id-n].d=mx;
}
// for(int i=1;i<=n;i++) printf("%d ",a[i]);printf("\n");
root[]=bt(,mx);
for(int i=;i<=n;i++)
root[i]=root[];
for(int i=;i<=n;i++)
add(i,a[i],);
for(int i=;i<=m;i++)
{
if(q[i].tmp==)
printf("%d\n",num[query(q[i].l,q[i].r,q[i].k)]);
else
{
add(q[i].x,a[q[i].x],-);
add(q[i].x,q[i].d,);
a[q[i].x]=q[i].d;//debug
}
}
return ;
}
【poj1901-求区间第k大值(带修改)】树状数组套主席树的更多相关文章
- ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解
题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...
- [bzoj3196][Tyvj1730]二逼平衡树_树套树_位置线段树套非旋转Treap/树状数组套主席树/权值线段树套位置线段树
二逼平衡树 bzoj-3196 Tyvj-1730 题目大意:请写出一个维护序列的数据结构支持:查询给定权值排名:查询区间k小值:单点修改:查询区间内定值前驱:查询区间内定值后继. 注释:$1\le ...
- Codeforces Round #404 (Div. 2) E. Anton and Permutation(树状数组套主席树 求出指定数的排名)
E. Anton and Permutation time limit per test 4 seconds memory limit per test 512 megabytes input sta ...
- 【树状数组套主席树】带修改区间K大数
P2617 Dynamic Rankings 题目描述给定一个含有n个数的序列a[1],a[2],a[3]……a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+ ...
- 【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)
http://www.lydsy.com/JudgeOnline/problem.php?id=1901 首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊. ...
- 【BZOJ 1901】【Zju 2112】 Dynamic Rankings 动态K值 树状数组套主席树模板题
达神题解传送门:http://blog.csdn.net/dad3zz/article/details/50638360 说一下我对这个模板的理解: 看到这个方法很容易不知所措,因为动态K值需要套树状 ...
- ZOJ 2112 Dynamic Rankings (动态第k大,树状数组套主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
- 学习笔记--函数式线段树(主席树)(动态维护第K极值(树状数组套主席树))
函数式线段树..资瓷 区间第K极值查询 似乎不过似乎划分树的效率更优于它,但是如果主席树套树状数组后,可以处理动态的第K极值.即资瓷插入删除,划分树则不同- 那么原理也比较易懂: 建造一棵线段树(权值 ...
- ZOJ 2112 Dynamic Rankings (动态第 K 大)(树状数组套主席树)
Dynamic Rankings Time Limit: 10 Seconds Memory Limit: 32768 KB The Company Dynamic Rankings has ...
随机推荐
- button type=“submit”
写js遇到任何怪异的行为 一定要先看看是不是submit搞的鬼. 函数内部最后总是返回 return false; 也是一个好的习惯
- week1 四人小组项目
小组名称:nice! 项目组长:李权 组员:于淼 刘芳芳 杨柳 项目选题:东北师范大学论坛 作为东北师范大学同学间的信息交流平台,要满足的需求如下: 1.校内信息及公告 2.毕业生招聘信息 3.课程查 ...
- Gitkraken系列-Gitkraken修改用户名
修改用户名 为了方便项目中代码的管理,需要重新编辑用户名. 点击右上角的图像即可看到如下图 3‑1所示的下拉菜单,鼠标悬于Profile上,会出现一个Edit按钮. 图 3‑1 编辑个人信息 点击Ed ...
- 第50天:scrollTo小火箭返回顶部
scrollTo(x,y)//可把内容滚动到指定的坐标scrollTo(xpos,ypos)//x,y值必需 1.固定导航栏 <!DOCTYPE html> <html lang=& ...
- Activiti5工作流笔记二
流程变量 import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import org.activiti ...
- HUAS 1483 mex(离线+线段树)
实在是太弱了.... 考虑离线,从mex[l,r]向mex[l,r+1]转移,显然是没啥东西可以记录的... 从mex[l,r]向mex[l+1,r]转移,记x=mex[l,r],如果[l+1,r]不 ...
- 【bzoj4417】[Shoi2013]超级跳马 矩阵乘法
题目描述 现有一个n行m列的棋盘,一只马欲从棋盘的左上角跳到右下角.每一步它向右跳奇数列,且跳到本行或相邻行.跳越期间,马不能离开棋盘.例如,当n = 3, m = 10时,下图是一种可行的跳法. ...
- javascript 文字闪烁
早上突然看到CSS里面的text-decoration属性的时候,发现blink仅有的火狐浏览器都不支持了.于是想使用js来实现这一效果. <script type="text/jav ...
- NOIP2017金秋冲刺训练营杯联赛模拟大奖赛第一轮Day2题解
上星期打的...题有点水,好多人都AK了 T1排个序贪心就好了 #include<iostream> #include<cstring> #include<cstdlib ...
- TYVJ1423 GF和猫咪的玩具
Description: GF同学和猫咪得到了一个特别的玩具,这个玩具由n个金属环(编号为1---n),和m条绳索组成,每条绳索连接两个不同的金属环,并且长度相同.GF左手拿起金属环L,猫咪右手(或者 ...