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

这题调了我相当长的时间,1wa1a,我是第一次写树套树,这个是树状数组套splay,在每个区间维护一棵树,然后将小于key的数量累计起来,因为这种做法不能直接找第k大,而要二分然后来判断排名是否==k-1。

ps:这里有个小地方我不能理解,是看绿云大神的代码的。就是二分那里,为什么最后还要return left,不是在二分里面当s==k-1的时候就return了吗。难道说还有其它原因??所以本题不能算ac,等绿云大神noi夺金回来了我再去问问他。。

#include <cstdio>
using namespace std;
const int N=10005, oo=~0u>>1;
#define lowbit(x) (x&-x)
struct node {
node* ch[2], *fa;
int key, size;
node() { ch[0]=ch[1]=fa=0; key=size=0; }
void pushup() { size=ch[0]->size+ch[1]->size+1; }
bool d() { return fa->ch[1]==this; }
void setc(node* c, bool d) { ch[d]=c; c->fa=this; }
}*null; struct Splay {
node* root;
Splay() { root=null; }
void rot(node* rt) {
node* fa=rt->fa; bool d=rt->d();
fa->fa->setc(rt, fa->d());
fa->setc(rt->ch[!d], d);
rt->setc(fa, !d);
fa->pushup();
if(root==fa) root=rt;
}
node* newnode(const int &key) {
node* ret=new node();
ret->key=key; ret->size=1;
ret->ch[0]=ret->ch[1]=ret->fa=null;
return ret;
}
void splay(node* rt, node* fa) {
while(rt->fa!=fa) {
if(rt->fa->fa==fa) rot(rt);
else rt->d()==rt->fa->d()?(rot(rt->fa), rot(rt)):(rot(rt), rot(rt));
}
rt->pushup();
}
void insert(const int& key) {
if(root==null) { root=newnode(key); return; }
node* t=root;
while(t->ch[key>t->key]!=null) t=t->ch[key>t->key];
node* c=newnode(key);
t->setc(c, key>t->key);
t->pushup();
splay(c, null);
}
void remove(const int &key) {
node* t=root;
while(t!=null && t->key!=key) t=t->ch[key>t->key];
if(t==null) return;
splay(t, null);
node* rt=root->ch[0];
if(rt==null) rt=root->ch[1];
else {
node* m=rt->ch[1];
while(m!=null && m->ch[1]!=null) m=m->ch[1];
if(m!=null) splay(m, root);
rt=root->ch[0];
rt->setc(root->ch[1], 1);
}
delete root;
root=rt;
root->fa=null;
if(root!=null) root->pushup();
}
int rank(const int& key) {
node* t=root;
int ret=0;
while(t!=null) {
if(t->key<key) {
ret+=t->ch[0]->size+1;
t=t->ch[1];
}
else t=t->ch[0];
}
return ret;
}
}*line[N], *nod[N], *q[N]; int cnt;
int getrank(int key) {
int ret=0;
for(int i=0; i<cnt; ++i)
ret+=q[i]->rank(key);
return ret;
}
int getans(int k, int l, int r) {
int r1=r, s;
cnt=0;
while(l<=r1) {
if(l<=r1-lowbit(r1)+1) {
q[cnt++]=line[r1];
r1-=lowbit(r1);
}
else {
q[cnt++]=nod[r1];
r1--;
}
}
int left=oo+1, right=oo;
for(int i=0; i<cnt; ++i) {
node* p=q[i]->root;
while(p!=null) {
if(p->key<left) {
p=p->ch[1];
continue;
}
if(p->key>right) {
p=p->ch[0];
continue;
}
s=getrank(p->key);
if(s==k-1) return p->key;
if(s<k-1) {
left=p->key;
p=p->ch[1];
}
else {
right=p->key;
p=p->ch[0];
}
}
}
return left;
} void init() {
null=new node(); null->ch[0]=null->ch[1]=null->fa=null;
}
int arr[N]; int main() {
int n, m;
init();
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) {
scanf("%d", &arr[i]);
line[i]=new Splay;
nod[i]=new Splay;
for(int j=i-lowbit(i)+1; j<=i; ++j)
line[i]->insert(arr[j]);
nod[i]->insert(arr[i]);
}
char str[3];
int a, b, c;
while(m--) {
scanf("%s", str);
if(str[0]=='Q') {
scanf("%d%d%d", &a, &b, &c);
printf("%d\n", getans(c, a, b));
}
else {
scanf("%d%d", &a, &b);
c=a;
while(c<=n) {
line[c]->remove(arr[a]);
line[c]->insert(b);
c+=lowbit(c);
}
nod[a]->root->key=b;
arr[a]=b;
}
}
return 0;
}

另一种做法,树状数组套主席树,比这个快多了。

http://www.cnblogs.com/iwtwiioi/p/3929957.html


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 区间k大 带修改 在线 线段树套平衡树

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

  2. bzoj 1901: Zju2112 Dynamic Rankings(树套树)

    1901: Zju2112 Dynamic Rankings 经典的带改动求区间第k小值问题 树套树模板,我是用的线段树套splay实现的,并且用的数组模拟的,所以可能空间略大,bzoj过了,zoj过 ...

  3. BZOJ 1901: Zju2112 Dynamic Rankings[带修改的主席树]【学习笔记】

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7143  Solved: 2968[Su ...

  4. Bzoj 1901: Zju2112 Dynamic Rankings 树套树,线段树,平衡树,Treap

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6471  Solved: 2697[Su ...

  5. Bzoj 1901: Zju2112 Dynamic Rankings 主席树,可持久,树状数组,离散化

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 6321  Solved: 2628[Su ...

  6. BZOJ 1901 Zju2112 Dynamic Rankings

    树阵主席设置树.维护间隔动态K大. .. ZOJ到空间太小,太大,仅仅能到BZOJ上交 1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memor ...

  7. BZOJ 1901: Zju2112 Dynamic Rankings( 树状数组套主席树 )

    裸的带修改主席树.. 之前用BIT套Splay( http://www.cnblogs.com/JSZX11556/p/4625552.html )A过..但是还是线段树好写...而且快(常数比平衡树 ...

  8. BZOJ 1901: Zju2112 Dynamic Rankings( BIT 套 BST )

    BIT 套 splay 其实也是不难...每个 BIT 的结点保存一颗 splay , 询问就二分答案然后判断rank... ------------------------------------- ...

  9. bzoj 1901: Zju2112 Dynamic Rankings -- 主席树,树状数组,哈希

    1901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MB Description 给定一个含有n个数的序列a[1] ...

  10. 【刷题】BZOJ 1901 Zju2112 Dynamic Rankings

    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. HDU2191多重背包例题

    悼念512汶川大地震遇难同胞——珍惜现在,感恩生活 Time Limit: 1000 MS Memory Limit: 32768 KB 64-bit integer IO format: %I64d ...

  2. 【Python】Django 支持 restful 风格 url

    URL通配符示例: url(r'^file_download/(?P<filename>(.)*)$', views.FILE_DOWNLOAD_VIEW.as_view()), 代码示例 ...

  3. 【Python】Django Model 怎么使用 UUID 作为主键?

    >>> import uuidprint uuid.uuid3(uuid.uuid1(), 'python.org') >>> # make a UUID base ...

  4. iOS CoreData学习资料 和 问题

    这里是另一篇好文章 http://blog.csdn.net/kesalin/article/details/6739319 这里是另一篇 http://hxsdit.com/1622 (不一定能访问 ...

  5. DP:Dollar Dayz(POJ 3181)

    一道高精度DP 题目大意,换工具,有m块钱,有k种价值的物品,(1...k),求一共有多少种换法 这一题就是完全背包,现在这种完全背包对我来说就是水题了, 状态转移方程闭着眼睛写dp[j]+=dp[j ...

  6. Extjs中给同一个GridPanel中的事件添加参数的方法

    Extjs中给同一个GridPanel中的事件添加参数的方法: this.isUse = new Ext.Action({            text:'启用',            scope ...

  7. Codeforces 390A( 模拟题)

    Inna and Alarm Clock Time Limit: 1000MS   Memory Limit: 262144KB   64bit IO Format: %I64d & %I64 ...

  8. [Android Pro] android 混淆文件project.properties和proguard-project.txt

    参考文档:http://blog.csdn.net/xueyepiaoling/article/details/8202359转载自:http://glblong.blog.51cto.com/305 ...

  9. July 29th, Week 31st Friday, 2016

    I am a slow walker, but I never walk backwards. 我走得很慢,但我从来不会后退. I had run very fast, and I had once ...

  10. Fedora 21 install chrome

    Steps to install Google Chrome on Fedora 21 A. Create google-chrome.repo file Use this command to cr ...