http://www.lydsy.com/JudgeOnline/problem.php?id=1901

首先还是吐槽时间,我在zoj交无限tle啊!!!!!!!!我一直以为是程序错了啊啊啊啊啊啊。

bzoj提交是wa!!T_T,将数组改大就acT_T

吐槽完毕。

这题之前做过,用树套树做的,但是时间感人(http://www.cnblogs.com/iwtwiioi/p/3870597.html

鉴于我是蒟蒻,所以我根本不会做啊!!

学习,,,

恩。。。

这题用树状数组来维护区间,写过树状数组套树的都应该会。和我之前的做法一样。

但是统计的话, 要多一步骤,就是将所有区间的主席树放进一个池子里面,然后才比较。

你懂得。

但是本题的重点不在这啊!!!

我也理解了很久。至于前面说的,本来就会了额。

离散化。。。很hentai。

我们首先要将所有的值都统计起来,因为主席树是离线的啊啊啊啊啊。。

然后用原来的方法离散确定区间。

然后询问没问题,另一个就是更新了。

不更新的主席树我们都会。更新的主席树照样很简单。

我们只要将原来的点删了,然后再补上。是不是很神奇啊。一点都不神奇,噗。

将原来点删了就是size-1。

然后你懂的。

一些东西写在代码里吧:

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;
#define lowbit(x) (x&-x)
#define read(x) x=getint()
#define rep(i, n) for(int i=0; i<n; ++i)
#define for1(i, a, n) for(int i=a; i<=(n); ++i)
#define MID (l+r)>>1
inline const int getint() { char c=getchar(); int k=1, r=0; for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
const int N=10005;
struct ND { int l, r, s; } t[N*200];
int tot, n, m, a[N], root[N], R[N], L[N], ans[N+N], cl, cr, cnt, QL[N], QR[N], K[N], num;
bool ask[N];
void update(const int &l, const int &r, int &pos, const int &key, const int &siz) {
t[++tot]=t[pos]; t[tot].s+=siz; pos=tot;
if(l==r) return;
int m=MID;
if(key<=m) update(l, m, t[pos].l, key, siz); else update(m+1, r, t[pos].r, key, siz);
}
inline void change(int x, const int &key, const int &siz) { for(; x<=n; x+=lowbit(x)) update(1, num, root[x], key, siz); }
int query(const int &l, const int &r, const int &k) {
if(l==r) return l;
int suml=0, sumr=0;
for1(i, 1, cl) suml+=t[t[L[i]].l].s;
for1(i, 1, cr) sumr+=t[t[R[i]].l].s;
int s=sumr-suml, m=MID;
if(k<=s) {
for1(i, 1, cl) L[i]=t[L[i]].l;
for1(i, 1, cr) R[i]=t[R[i]].l;
return query(l, m, k);
}
else {
for1(i, 1, cl) L[i]=t[L[i]].r;
for1(i, 1, cr) R[i]=t[R[i]].r;
return query(m+1, r, k-s);
}
}
inline int getans(int l, int r, const int &k) {
for(cl=0; l>0; l-=lowbit(l)) L[++cl]=root[l];
for(cr=0; r>0; r-=lowbit(r)) R[++cr]=root[r];
return query(1, num, k);
}
int main() {
read(n); read(m); char c;
for1(i, 1, n) read(a[i]), ans[++cnt]=a[i];
for1(i, 1, m) {
for(c=getchar(); c<'A'||c>'Z'; c=getchar());
read(QL[i]); read(QR[i]);
if(c=='Q') read(K[i]), ask[i]=1;
else ans[++cnt]=QR[i];
}
sort(ans+1, ans+1+cnt); //咱们先离散,在这里用不着再开个域id了
ans[cnt+1]=1000000013;
for1(i, 1, cnt) if(ans[i]!=ans[i+1]) ans[++num]=ans[i]; //将重复的累起来,缩小主席树的区间
for1(i, 1, n) a[i]=lower_bound(ans+1, ans+1+num, a[i])-ans; //查找原来数据在新数据的位置,这里可以直接覆盖了
for1(i, 1, n) change(i, a[i], 1);
for1(i, 1, m) {
if(ask[i]) printf("%d\n", ans[getans(QL[i]-1, QR[i], K[i])]);
else {
change(QL[i], a[QL[i]], -1); //先将原来的剪掉
a[QL[i]]=lower_bound(ans+1, ans+1+num, QR[i])-ans; //改变位置
change(QL[i], a[QL[i]], 1); //再将新的加上
}
} return 0;
}

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

5 3
3 2 1 4 7
Q 1 4 3
C 2 6
Q 2 5 3

Sample Output

3
6

HINT

20%的数据中,m,n≤100; 40%的数据中,m,n≤1000; 100%的数据中,m,n≤10000。

Source

【BZOJ】1901: Zju2112 Dynamic Rankings(区间第k小+树状数组套主席树)的更多相关文章

  1. BZOJ 1901 Zju2112 Dynamic Rankings ——树状数组套主席树

    [题目分析] BZOJ这个题目抄的挺霸气. 主席树是第一时间想到的,但是修改又很麻烦. 看了别人的题解,原来还是可以用均摊的思想,用树状数组套主席树. 学到了新的姿势,2333o(* ̄▽ ̄*)ブ [代 ...

  2. ZOJ 2112 Dynamic Rankings(树状数组套主席树 可修改区间第k小)题解

    题意:求区间第k小,节点可修改 思路:如果直接用静态第k小去做,显然我更改一个节点后,后面的树都要改,这个复杂度太高.那么我们想到树状数组思路,树状数组是求前缀和,那么我们可以用树状数组套主席树,求出 ...

  3. P2617 Dynamic Rankings(树状数组套主席树)

    P2617 Dynamic Rankings 单点修改,区间查询第k大 当然是无脑树套树了~ 树状数组套主席树就好辣 #include<iostream> #include<cstd ...

  4. LUOGU P2617 Dynamic Rankings(树状数组套主席树)

    传送门 解题思路 动态区间第\(k\)大,树状数组套主席树模板.树状数组的每个位置的意思的是每棵主席树的根,维护的是一个前缀和.然后询问的时候\(log\)个点一起做前缀和,一起移动.时空复杂度\(O ...

  5. BZOJ 3196 Tyvj 1730 二逼平衡树 ——树状数组套主席树

    [题目分析] 听说是树套树.(雾) 怒写树状数组套主席树,然后就Rank1了.23333 单点修改,区间查询+k大数查询=树状数组套主席树. [代码] #include <cstdio> ...

  6. BZOJ 2141 排队(树状数组套主席树)

    解法很多的题,可以块套树状数组,可以线段树套平衡树.我用的是树状数组套主席树. 题意:给出一段数列,m次操作,每次操作是交换两个位置的数,求每次操作后的逆序对数.(n,m<=2e4). 对于没有 ...

  7. BZOJ.1901.Dynamic Rankings(树状数组套主席树(动态主席树))

    题目链接 BZOJ 洛谷 区间第k小,我们可以想到主席树.然而这是静态的,怎么支持修改? 静态的主席树是利用前缀和+差分来求解的,那么对于每个位置上的每棵树看做一个点,拿树状数组更新. 还是树状数组的 ...

  8. BZOJ1901 - Dynamic Rankings(树状数组套主席树)

    题目大意 给定一个有N个数字的序列,然后又m个指令,指令种类只有两种,形式如下: Q l r k 要求你查询区间[l,r]第k小的数是哪个 C i t  要求你把第i个数修改为t 题解 动态的区间第k ...

  9. BZOJ 1901: Zju2112 Dynamic Rankings 区间k大 带修改 在线 线段树套平衡树

    之前写线段树套splay数组版..写了6.2k..然后弃疗了.现在发现还是很水的..嘎嘎.. zju过不了,超时. upd:才发现zju是多组数据..TLE一版才发现.然后改了,MLE...手写内存池 ...

随机推荐

  1. PHP session的实现原理

    PHP SESSION原理 我们知道,session是在服务器端保持用户会话数据的一种方法,对应的cookie是在客户端保持用户数据.HTTP协议是一种无状态协议,服务器响应完之后就失去了与浏览器的联 ...

  2. PHP--TP框架----操作数据库

    //操作数据库                    //$attr = $m->select(); //查询所有数据                    //$attr = $m->s ...

  3. HDU 5510 Bazinga (字符串匹配)

    题目:传送门. 题意:t 组数据,每组 n 个串,对于第 i 个串如果存在 1 到 i-1 中的某个串不是 i 的子串,那么这个第 i 个串符合题意,求 i 的最大值. 题解:KMP,AC自动机也可以 ...

  4. HDU1297 Children’s Queue (高精度+递推)

    Children’s Queue Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) ...

  5. HDU 4059 容斥原理+快速幂+逆元

    E - The Boss on Mars Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

  6. July 27th, Week 31st Wednesday, 2016

    Don't let yesterday take up too much of today. 别让昨天的事情占据今天太多时间. Learn from yesterday, but don't let ...

  7. July 19th, Week 30th Tuesday, 2016

    The good seaman is known in bad weather. 惊涛骇浪,方显英雄本色. You can't be afraid to fail. It's the only way ...

  8. Genesis自动登录方法(免输入用户名和密码)

    第一步:点击“我的电脑”右键属性在“高级”里面的“环境变量”里面把“系统变量”照下图所示新建(XP和WIN7的环境变量设置方法类似): 变量名:FRONTLINE_NO_LOGIN_SCREEN 变量 ...

  9. Android 图标添加消息提醒

    实现方法: 1. 在对应的布局放置TextView或者ImageView. 2. 用Canvas在原来Icon的bitmap基础上进行绘制 3. 利用开源项目ViewBadger进行添加,很方便,而且 ...

  10. pyinstaller--将py文件转化成exe

    首先要注意一下:打包python文件成exe格式这个过程只能在windows环境下运行 1. 直接在命令行用pip安装 pyinstaller pip install pyinstaller</ ...