• [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

    数据规模及约定

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

    题解

    线段树套线段树来一发。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    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 maxval 1000000000
    #define maxn 10010
    #define maxnode 4200010
    int n;
    
    int ToT, sumv[maxnode], lc[maxnode], rc[maxnode], recs[maxnode], rcnts;
    int getsnode() {
    	if(rcnts) {
    		int o = recs[rcnts--];
    		sumv[o] = lc[o] = rc[o] = 0;
    		return o;
    	}
    	return ++ToT;
    }
    void update(int& o, int l, int r, int x, int v) {
    	if(!o) o = getsnode();
    	if(l == r) {
    		sumv[o] += v;
    		if(!sumv[o]) recs[++rcnts] = o, o = 0;
    		return ;
    	}
    	int mid = l + r >> 1;
    	if(x <= mid) update(lc[o], l, mid, x, v);
    	else update(rc[o], mid + 1, r, x, v);
    	sumv[o] = (lc[o] ? sumv[lc[o]] : 0) + (rc[o] ? sumv[rc[o]] : 0);
    	if(!sumv[o]) recs[++rcnts] = o, o = 0;
    	return ;
    }
    
    int rt[maxn<<2], No[maxn], cn;
    void modify(int L, int R, int o, int p, int x, int v) {
    	update(rt[o], 0, maxval, x, v);
    	if(L == R) return ;
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(p <= M) modify(L, M, lc, p, x, v);
    	else modify(M+1, R, rc, p, x, v);
    	return ;
    }
    void query(int L, int R, int o, int ql, int qr) {
    	if(ql <= L && R <= qr){ No[++cn] = rt[o]; return ; }
    	int M = L + R >> 1, lc = o << 1, rc = lc | 1;
    	if(ql <= M) query(L, M, lc, ql, qr);
    	if(qr > M) query(M+1, R, rc, ql, qr);
    	return ;
    }
    
    int solve(int ql, int qr, int k) {
    	cn = 0; query(1, n, 1, ql, qr);
    	int l = 0, r = maxval;
    	while(l < r) {
    		int mid = l + r >> 1, sum = 0;
    		for(int i = 1; i <= cn; i++) if(No[i] && lc[No[i]]) sum += sumv[lc[No[i]]];
    		if(sum < k) {
    			k -= sum; l = mid + 1;
    			for(int i = 1; i <= cn; i++) if(No[i]) No[i] = rc[No[i]];
    		}
    		else {
    			r = mid;
    			for(int i = 1; i <= cn; i++) if(No[i]) No[i] = lc[No[i]];
    		}
    	}
    	return l;
    }
    
    int val[maxn];
    int main() {
    	n = read(); int q = read();
    	for(int i = 1; i <= n; i++) val[i] = read(), modify(1, n, 1, i, val[i], 1);
    	char cmd[2];
    	while(q--) {
    		scanf("%s", cmd);
    		if(cmd[0] == 'Q') {
    			int ql = read(), qr = read(), k = read();
    			printf("%d
    ", solve(ql, qr, k));
    		}
    		if(cmd[0] == 'C') {
    			int x = read(), v = read();
    			modify(1, n, 1, x, val[x], -1);
    			val[x] = v;
    			modify(1, n, 1, x, val[x], 1);
    		}
    	}
    	
    	return 0;
    }
    

    树状数组套主席树来一发。

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #include <stack>
    #include <vector>
    #include <queue>
    #include <cstring>
    #include <string>
    #include <map>
    #include <set>
    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 maxval 1000000000
    #define maxn 10010
    #define maxnode 4200010
    int n, rt[maxn], val[maxn];
    
    int ToT, sumv[maxnode], lc[maxnode], rc[maxnode];
    void update(int& y, int x, int l, int r, int p, int v) {
    	sumv[y = ++ToT] = sumv[x] + v;
    	if(l == r) return ;
    	int mid = l + r >> 1; lc[y] = lc[x]; rc[y] = rc[x];
    	if(p <= mid) update(lc[y], lc[x], l, mid, p, v);
    	else update(rc[y], rc[x], mid + 1, r, p, v);
    	return ;
    }
    
    int Rt[maxn], lrt[maxn], rrt[maxn], cl, cr;
    void modify(int p, int x, int v) {
    	for(; p <= n; p += p & -p) update(Rt[p], Rt[p], 0, maxval, x, v);
    	return ;
    }
    void query(int ql, int qr) {
    	cl = cr = 0;
    	ql--; lrt[++cl] = rt[ql];
    	for(; ql; ql -= ql & -ql) lrt[++cl] = Rt[ql];
    	rrt[++cr] = rt[qr];
    	for(; qr; qr -= qr & -qr) rrt[++cr] = Rt[qr];
    	return ;
    }
    
    int solve(int ql, int qr, int k) {
    	query(ql, qr);
    	int l = 0, r = maxval;
    	while(l < r) {
    		int mid = l + r >> 1, sum = 0;
    		for(int i = 1; i <= cr; i++) if(rrt[i] && lc[rrt[i]]) sum += sumv[lc[rrt[i]]];
    		for(int i = 1; i <= cl; i++) if(lrt[i] && lc[lrt[i]]) sum -= sumv[lc[lrt[i]]];
    		if(sum < k) {
    			k -= sum; l = mid + 1;
    			for(int i = 1; i <= cl; i++) if(lrt[i]) lrt[i] = rc[lrt[i]];
    			for(int i = 1; i <= cr; i++) if(rrt[i]) rrt[i] = rc[rrt[i]];
    		}
    		else {
    			r = mid;
    			for(int i = 1; i <= cl; i++) if(lrt[i]) lrt[i] = lc[lrt[i]];
    			for(int i = 1; i <= cr; i++) if(rrt[i]) rrt[i] = lc[rrt[i]];
    		}
    	}
    	return l;
    }
    
    int main() {
    	n = read(); int q = read();
    	for(int i = 1; i <= n; i++) {
    		val[i] = read();
    		update(rt[i], rt[i-1], 0, maxval, val[i], 1);
    	}
    	char cmd[2];
    	while(q--) {
    		scanf("%s", cmd);
    		if(cmd[0] == 'Q') {
    			int ql = read(), qr = read(), k = read();
    			printf("%d
    ", solve(ql, qr, k));
    		}
    		if(cmd[0] == 'C') {
    			int x = read(), v = read();
    			modify(x, val[x], -1);
    			modify(x, val[x] = v, 1);
    		}
    	}
    	
    	return 0;
    }
    
  • 相关阅读:
    Python Data Analysis Library¶
    matadon/mizuno
    MySQL 5.1参考手册
    Apache Derby: Quick Start
    JRuby大捷:ThoughtWorks宣布Mingle发布在即
    RailsWithH2InJNDIOnJetty
    Embedded Jetty and Spring: The Lightweight Antidote for Java EE Complexity
    window下安装解压缩版mysql/zip压缩文件包非install安装程序
    Chapter 9. Extending Workbench
    Mysql手动增加一列_Blog of Grow_百度空间
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/6349824.html
Copyright © 2020-2023  润新知