zoukankan      html  css  js  c++  java
  • 【模板】主席树

    1.静态区间第k小

    题解思路

    对于每个位置维护一个线段树,显然每个线段树维护的信息可以加减
    所以通过类似前缀和的思想求区间第k小

    代码

    #include <cstdio>
    #include <algorithm>
    #define ci const int
    #define mid ((l+r)>>1)
    ci Maxn=200010;
    int n,m,N,l,r,k;
    int a[Maxn],b[Maxn],T[Maxn];
    struct Node {
    	int cnt;
    	int s[Maxn<<5],ls[Maxn<<5],rs[Maxn<<5];
    	int build(ci& l,ci& r) {
    		int rt=++cnt;
    		if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
    		return rt;
    	}
    	int modify(ci& pre,ci& l,ci& r,ci& x) {
    		int rt=++cnt;
    		s[rt]=s[pre]+1;ls[rt]=ls[pre];rs[rt]=rs[pre];
    		if (l^r) x<=mid?ls[rt]=modify(ls[pre],l,mid,x):rs[rt]=modify(rs[pre],mid+1,r,x);
    		return rt;
    	}
    	int query(ci& L,ci& R,ci& l,ci& r,ci& k) {
    		if (l==r) return l;
    		int xx=s[ls[R]]-s[ls[L]];
    		return k<=xx?query(ls[L],ls[R],l,mid,k):query(rs[L],rs[R],mid+1,r,k-xx);
    	}
    }sgt;
    int main() {
    	scanf("%d%d",&n,&m);
    	for (register int i=1;i<=n;++i) scanf("%d",&a[i]),b[i]=a[i];
    	std::sort(b+1,b+n+1); N=std::unique(b+1,b+n+1)-b-1;
    	T[0]=sgt.build(1,N);
    	for (register int i=1;i<=n;++i) T[i]=sgt.modify(T[i-1],1,N,std::lower_bound(b+1,b+N+1,a[i])-b);
    	for (register int i=1;i<=m;++i) {
    		scanf("%d%d%d",&l,&r,&k);
    		printf("%d
    ",b[sgt.query(T[l-1],T[r],1,N,k)]);
    	}
    }
    

    2.可持久化数组

    题意简述

    维护一个数组,支持查询或修改某一历史版本某一位置的值

    代码

    #include <cstdio>
    #include <algorithm>
    #define ci const int
    #define mid ((l+r)>>1)
    ci Maxn=1000010;
    int n,m,pre,opt,loc,val;
    int a[Maxn],T[Maxn];
    struct Node {
    	int cnt;
    	int va[Maxn<<4],ls[Maxn<<4],rs[Maxn<<4];
    	int build(ci& l,ci& r) {
    		int rt=++cnt;
    		if (l^r) ls[rt]=build(l,mid),rs[rt]=build(mid+1,r);
    		else va[rt]=a[l];
    		return rt;
    	}
    	int modify(ci& pre,ci& l,ci& r) {
    		int rt=++cnt;
    		va[rt]=va[pre];ls[rt]=ls[pre];rs[rt]=rs[pre];
    		if (l^r) loc<=mid?ls[rt]=modify(ls[pre],l,mid):rs[rt]=modify(rs[pre],mid+1,r);
    		else va[rt]=val;
    		return rt;
    	}
    	int query(ci& edt,ci& l,ci& r) {
    		if (l==r) return va[edt];
    		return loc<=mid?query(ls[edt],l,mid):query(rs[edt],mid+1,r);
    	}
    }sgt;
    int main() {
    	scanf("%d%d",&n,&m);
    	for (register int i=1;i<=n;++i) scanf("%d",&a[i]);
    	T[0]=sgt.build(1,n);
    	for (register int i=1;i<=m;++i) {
    		scanf("%d%d%d",&pre,&opt,&loc);
    		if (opt==1) scanf("%d",&val),T[i]=sgt.modify(T[pre],1,n);
    		else printf("%d
    ",sgt.query(T[pre],1,n)),T[i]=T[pre];
    	}
    }
    
  • 相关阅读:
    递归斐波那契数列时间复杂度
    动态规划 矩阵链乘法
    kmp算法
    贪心 单源最短路径
    贪心法 背包问题求解
    贪心法 货币支付问题或找零问题
    贪心算法简介
    排列问题的递归算法和非递归算法
    php __set() __get() __isset() __unset()四个方法的应用
    使用栈结构完毕四则运算
  • 原文地址:https://www.cnblogs.com/xuyixuan/p/11298106.html
Copyright © 2011-2022 走看看