zoukankan      html  css  js  c++  java
  • 主席树动态

    以ZOJ2114为模板题。

    附上此题链接

    主席树的动态单点改值主要是主席树加树状数组,具体暂未理解,待熟练仔细揣摩。

    代码如下

    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    const int maxn = 60000;
    struct NOOD {
    	bool kind;
    	int l, r, k, v;
    }Q[maxn + 5];
    int a[maxn + 5], t[2 * maxn + 5];
    int root[maxn * 32 + 5], L[maxn * 32 + 5], R[maxn * 32 + 5], cnt[maxn * 32 + 5];
    int S[maxn + 5], ul[maxn + 5], ur[maxn + 5];
    int n, m, q, tot;
    void Build(int &rt, int l, int r) {
    	rt = ++tot;
    	cnt[rt] = 0;
    	if(l == r) return ;
    	int mid = (l + r) / 2;
    	Build(L[rt], l, mid);
    	Build(R[rt], mid + 1, r);
    }
    void Insert(int &rt, int pre, int l, int r, int x, int val) {
    	rt = ++tot;
    	L[rt] = L[pre];
    	R[rt] = R[pre];
    	cnt[rt] = cnt[pre] + val;
    	if(l == r)return ;
    	int mid = (l + r) / 2;
    	if(x <= mid)Insert(L[rt], L[pre], l, mid, x, val);
    	else Insert(R[rt], R[pre], mid + 1, r, x, val);
    }
    int lowbit(int x){return x & -x;}
    void add(int x, int val) {
    	int pos = lower_bound(t + 1, t + m + 1, a[x]) - t;
    	while(x <= n) {
    		Insert(S[x], S[x], 1, m, pos, val);
    		x += lowbit(x);
    	}
    }
    int Sum(int x, bool kind) {
    	int res = 0;
    	while(x > 0) {
    		if(kind == 0)res += cnt[L[ur[x]]];
    		else res += cnt[L[ul[x]]];
    		x -= lowbit(x);
    	}
    	return res;
    }
    int Query(int posl, int posr, int nodel, int noder, int l, int r, int k) {
    	if(l == r)return l;
    	int mid = (l + r) / 2;
    	int num = Sum(posr, 0) - Sum(posl, 1) + cnt[L[noder]] - cnt[L[nodel]];//暂未明白此处树状数组求法
    	if(k <= num) {
    		for(int i = posr; i ; i -= lowbit(i))ur[i] = L[ur[i]];
    		for(int i = posl; i ; i -= lowbit(i))ul[i] = L[ul[i]];
    		return Query(posl, posr, L[nodel], L[noder], l, mid, k);
    	}
    	else {
    		for(int i = posr; i ; i -= lowbit(i))ur[i] = R[ur[i]];
    		for(int i = posl; i ; i -= lowbit(i))ul[i] = R[ul[i]];
    		return Query(posl, posr, R[nodel], R[noder], mid + 1, r, k - num);
    	}
    }
    
    void Init() {
    	tot = 0;
    	scanf("%d%d", &n, &q);
    	for(int i = 1; i <= n; t[i] = a[i], i++)scanf("%d", &a[i]);
    	m = n;
    	for(int i = 1; i <= q; i++) {
    		char ch; scanf(" %c", &ch);
    		if(ch == 'Q') {
    			Q[i].kind = 0; 
    			scanf("%d%d%d", &Q[i].l, &Q[i].r, &Q[i].k);
    		}
    		else {
    			Q[i].kind = 1; 
    			scanf("%d%d", &Q[i].l, &Q[i].v);
    			t[++m] = Q[i].v;
    		}
    	}
    	sort(t + 1, t + m + 1);
    	m = unique(t + 1, t + m + 1) - t - 1;
    }
    int main() {
    	int T; scanf("%d", &T);
    	while(T--) {
    		Init();
    		Build(root[0], 1, m);
    		for(int i = 1; i <= n; i++) {
    			int pos = lower_bound(t + 1, t + m + 1, a[i]) - t;
    			Insert(root[i], root[i - 1], 1, m, pos, 1);
    			S[i] = root[0];
    		}
    		for(int i = 1; i <= q; i++) {
    			if(Q[i].kind == 0) {
    				for(int j = Q[i].r; j ; j -= lowbit(j))ur[j] = S[j];
    				for(int j = Q[i].l - 1; j ; j -= lowbit(j))ul[j] = S[j];
    				printf("%d
    ", t[Query(Q[i].l - 1, Q[i].r, root[Q[i].l - 1], root[Q[i].r], 1, m, Q[i].k)]);
    			}
    			else {
    				add(Q[i].l, -1);
    				a[Q[i].l] = Q[i].v;
    				add(Q[i].l, 1);
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    AES加解密
    redis HyperLogLog使用
    vi常用操作
    redis string使用
    用jdk命令定位java应用问题
    用户态、内核态及零拷贝
    缓存穿透与雪崩
    ReentrantLock、Semaphore、AQS
    redis list使用
    不同数据库取并集、交集、差集
  • 原文地址:https://www.cnblogs.com/TRDD/p/9813500.html
Copyright © 2011-2022 走看看