zoukankan      html  css  js  c++  java
  • luogu3834 【模板】可持久化线段树 1(主席树)

    题目

    luogu3834

    代码

    #include <iostream>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    #define N 500005
    #define M 10000000
    using namespace std; 
    
    int n,m,rk[N];
    int root[N];
    
    struct data{int id,num;}a[N];
    bool cmp(data x,data y){return x.num<y.num;}
    struct node{int l,r,sz;}T[M];
    
    int cnt;
    void insert(int &rt,int x,int y,int p)
    {
    	T[++cnt]=T[rt];rt=cnt;
    	T[rt].sz++;//sz记录子树中被标记的结点个数 
    	if(x==y) return;
    	int mid=(x+y)>>1;
    	if(p<=mid) insert(T[rt].l,x,mid,p);
    	else insert(T[rt].r,mid+1,y,p);
    }
    
    int query(int ql,int qr,int x,int y,int k)
    {
    	if(x==y) return x;
    	int t=T[T[qr].l].sz-T[T[ql].l].sz;
    	int mid=(x+y)>>1;
    	if(k<=t) return query(T[ql].l,T[qr].l,x,mid,k);
    	else return query(T[ql].r,T[qr].r,mid+1,y,k-t);
    }
    
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<=n;i++) scanf("%d",&a[i].num),a[i].id=i;
    	sort(a+1,a+1+n,cmp);
    	for(int i=1;i<=n;i++) rk[a[i].id]=i;//rk[i]记录在原序列的位置为i的数是第几大 
    	for(int i=1;i<=n;i++)
    	{
    		root[i]=root[i-1];//root[i]记录前i个数构成的线段树的根
    		insert(root[i],1,n,rk[i]); 
    	}
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,k;scanf("%d%d%d",&x,&y,&k);
    		printf("%d
    ",a[query(root[x-1],root[y],1,n,k)].num);//类比sum[r]-sum[i-1] 
    	}
    	return 0;
    }
  • 相关阅读:
    计算组合数
    UVa11889
    UVa11388
    二分查找
    UVa12096
    UVa156
    UVa400
    京东2017校招编程题
    华为2017秋招测试工程师笔试试卷
    剑指offer第七章&第八章
  • 原文地址:https://www.cnblogs.com/XYZinc/p/7598424.html
Copyright © 2011-2022 走看看