• [BZOJ1901]Zju2112 Dynamic Rankings


    [BZOJ1901]Zju2112 Dynamic Rankings

    试题描述

    给定一个含有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。

    输入

    输出

    对于每一次询问,你都需要输出他的答案,每一个输出占单独的一行。

    输入示例

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

    输出示例

    3
    6

    数据规模及约定

    见“试题描述

    题解

    打了一波线段树套 treap,相比于主席树套树状数组来说慢多了。。。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    
    int read() {
    	int x = 0, f = 1; char c = getchar();
    	while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
    	while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
    	return x * f;
    }
    
    #define maxn 10005
    #define maxnode 1280010
    struct Node {
    	int v, r, siz;
    	Node() {}
    	Node(int _, int __): v(_), r(__) {}
    } ns[maxnode];
    int ToT, rt[maxn<<2], fa[maxnode], ch[2][maxnode];
    void maintain(int o) {
    	ns[o].siz = 1;
    	for(int i = 0; i < 2; i++) if(ch[i][o])
    		ns[o].siz += ns[ch[i][o]].siz;
    	return ;
    }
    void rotate(int u) {
    	int y = fa[u], z = fa[y], l = 0, r = 1;
    	if(z) ch[ch[1][z]==y][z] = u;
    	if(ch[1][y] == u) swap(l, r);
    	fa[u] = z; fa[y] = u; fa[ch[r][u]] = y;
    	ch[l][y] = ch[r][u]; ch[r][u] = y;
    	maintain(y); maintain(u);
    	return ;
    }
    void insert(int& o, int v) {
    	if(!o) {
    		ns[o = ++ToT] = Node(v, rand());
    		return maintain(o);
    	}
    	bool d = v > ns[o].v;
    	insert(ch[d][o], v); fa[ch[d][o]] = o;
    	if(ns[ch[d][o]].r > ns[o].r) {
    		int t = ch[d][o];
    		rotate(t); o = t;
    	}
    	return maintain(o);
    }
    void del(int& o, int v) {
    	if(!o) return ;
    	if(ns[o].v == v) {
    		if(!ch[0][o] && !ch[1][o]) o = 0;
    		else if(!ch[0][o]) {
    			int t = ch[1][o]; fa[t] = fa[o]; o = t;
    		}
    		else if(!ch[1][o]) {
    			int t = ch[0][o]; fa[t] = fa[o]; o = t;
    		}
    		else {
    			bool d = ns[ch[1][o]].r > ns[ch[0][o]].r;
    			int t = ch[d][o]; rotate(t); o = t;
    			del(ch[d^1][o], v);
    		}
    	}
    	else {
    		bool d = v > ns[o].v;
    		del(ch[d][o], v);
    	}
    	return maintain(o);
    }
    int Find(int o, int v) {
    	if(!o) return 0;
    	int ls = ch[0][o] ? ns[ch[0][o]].siz : 0;
    	if(v >= ns[o].v) return ls + 1 + Find(ch[1][o], v);
    	return Find(ch[0][o], v);
    }
    
    int n, val[maxn];
    void build(int L, int R, int o, int p) {
    	insert(rt[o], val[p]);
    	if(L == R) return ;
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(p <= M) build(L, M, lc, p);
    	else build(M+1, R, rc, p);
    	return ;
    }
    void update(int L, int R, int o, int p, int v) {
    	del(rt[o], val[p]); insert(rt[o], v);
    	if(L == R) return ;
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(p <= M) update(L, M, lc, p, v);
    	else update(M+1, R, rc, p, v);
    	return ;
    }
    int ql, qr;
    int query(int L, int R, int o, int v) {
    	if(ql <= L && R <= qr) return Find(rt[o], v);
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1, ans = 0;
    	if(ql <= M) ans += query(L, M, lc, v);
    	if(qr > M) ans += query(M+1, R, rc, v);
    	return ans;
    }
    
    int main() {
    	n = read(); int q = read();
    	for(int i = 1; i <= n; i++) val[i] = read(), build(1, n, 1, i);
    	
    	while(q--) {
    		char tp[2]; scanf("%s", tp);
    		if(tp[0] == 'Q') {
    			ql = read(); qr = read(); int k = read();
    			int l = 0, r = (int)1e9; bool has = 0;
    			while(l < r) {
    				int mid = l + r >> 1;
    				if(query(1, n, 1, mid) < k) {
    					l = mid + 1;
    					if(query(1, n, 1, l) >= k){ has = 1; printf("%d
    ", l); break; }
    				}
    				else r = mid;
    			}
    			if(!has) printf("%d
    ", l);
    		}
    		else {
    			int p = read(), v = read();
    			update(1, n, 1, p, v);
    			val[p] = v;
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    学习shell script
    ubuntu11.10安装出现/cdrom问题以及不能格式成ext问题
    正则表达式
    认识与学习bash(2)
    UNIX网络编程 一个简单的时间获取客户程序
    HDU4522
    恢复引导
    认识与学习bash(1)
    文件格式化处理
    C++解析csv文件
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6155889.html
Copyright © 2020-2023  润新知