划分树 模板

#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std; 

#define N 100500 

#define MID ((l+r)>>1)
int a[N],s[N],t[20][N],num[20][N],n,m; 

//  void build(int lft,int rht,int ind)
//	{
//		if(lft==rht) return;
//
//		int mid=MID(lft,rht);
//		int same=mid-lft+1,ln=lft,rn=mid+1;
//		for(int i=lft;i<=rht;i++)
//			if(valu[ind][i]<order[mid]) same--;
//		for(int i=lft;i<=rht;i++)
//		{
//			int flag=0;
//			if((valu[ind][i]<order[mid])||(valu[ind][i]==order[mid]&&same))//划分到左区间
//			{
//				flag=1;
//				valu[ind+1][ln++]=valu[ind][i];
//				lsum[ind][i]=lsum[ind][i-1]+valu[ind][i];
//				if(valu[ind][i]==order[mid]) same--;
//			}
//			else //划分到右区间
//			{
//				valu[ind+1][rn++]=valu[ind][i];
//				lsum[ind][i]=lsum[ind][i-1];
//			}
//			num[ind][i]=num[ind][i-1]+flag;//划分到左区间的个数
//		}
//		build(lft,mid,ind+1);
//		build(mid+1,rht,ind+1);
//	}
//  int query(int st,int ed,int k,int lft,int rht,int ind)//子区间[st,ed],大区间[lft,rht],层数ind
//	{
//		if(lft==rht) return valu[ind][lft];
//
//		int mid=MID(lft,rht);
//		int lx=num[ind][st-1]-num[ind][lft-1];//在左区间不属于子区间的个数
//		int ly=num[ind][ed]-num[ind][st-1];//有多少个进入左区间
//		int rx=st-1-lft+1-lx;//在右区间不属于子区间的个数
//		int ry=ed-st+1-ly;//有多少个进入右区间
//		if(ly>=k) return query(lft+lx,lft+lx+ly-1,k,lft,mid,ind+1);
//		else
//		{
//			isum+=lsum[ind][ed]-lsum[ind][st-1];
//			st=mid+1+rx;
//			ed=mid+1+rx+ry-1;
//			return query(st,ed,k-ly,mid+1,rht,ind+1);
//		}
//	}
void Build(int c,int l,int r)
{
    int lm=MID-l+1,lp=l,rp=MID+1;
    for(int i=l;i<=MID;i++)
        lm-=s[i]<s[MID];
    for(int i=l;i<=r;i++)
    {
        if( i==l )
            num[c][i]=0;
        else
            num[c][i]=num[c][i-1];
        if( t[c][i]==s[MID] )
        {
            if( lm )
            {
                lm--;
                num[c][i]++;
                t[c+1][lp++]=t[c][i];
            }
            else
                t[c+1][rp++]=t[c][i];
        }
        else if( t[c][i]<s[MID] )
        {
            num[c][i]++;
            t[c+1][lp++]=t[c][i];
        }
        else
            t[c+1][rp++]=t[c][i];
    }
    if( l<r )
        Build(c+1,l,MID),Build(c+1,MID+1,r);
} 

int Query(int c,int l,int r,int ql,int qr,int k)
{
    if( l==r )
        return t[c][l];
    int s,ss;
    if( l==ql )
        s=0,ss=num[c][qr];
    else
        s=num[c][ql-1],ss=num[c][qr]-num[c][ql-1];
    if( k<=ss )
        return Query(c+1,l,MID,l+s,l+s+ss-1,k);
    else
        return Query(c+1,MID+1,r,MID+1+ql-l-s,MID+1+qr-l-s-ss,k-ss);
} 

int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&a[i]);
        s[i]=t[0][i]=a[i];
    }
    sort(s+1,s+1+n);
    Build(0,1,n);
    while( m-- )
    {
        int l,r,k;
        scanf("%d%d%d",&l,&r,&k);
        printf("%d\n",Query(0,1,n,l,r,k));
    }
    return 0;
}
/*
10 10
0 5 2 7 5 4 3 8 7 7
2 8 3
3 5 2
1 3 1
1 9 4
1 2 2
3 5 3
5 5 1
4 6 3
1 5 4
5 7 3

8 6
2 4 3 5 8 1 7 6
2 7 2
*/

划分树 模板

时间: 2024-11-08 01:28:23

划分树 模板的相关文章

poj 2104 K-th Number(划分树模板)

划分树模板题,敲上模板就ok了. #include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<cstdio> #include<cmath> #include<queue> #include<stack> #include<map> #include<set> #define MP

POJ--2104--K-th Number【划分树模板】

链接:http://poj.org/problem?id=2104 题意:给一个n个元素的数组,m次询问,每次查询区间[i,j]中第k大的数,输出这个数. 思路:划分树模板题 划分树讲解:传送门 我用的是kuangbin大神的模板 #include<cstring> #include<string> #include<fstream> #include<iostream> #include<iomanip> #include<cstdio&

划分树模板

1 ///划分树模板,找区间第k小的数 2 const int mx=1e5+5; 3 int tree[30][mx]; 4 int sortt[mx]; 5 int sum[30][mx]; 6 7 void build(int l,int r,int c) 8 { 9 if (l==r) return ; 10 int m=(l+r)>>1; 11 int isame=m-l+1; 12 int pl=l,pr=m+1; 13 for (int i=l;i<m;i++) 14 if

划分树模板题

原题http://poj.org/problem?id=2104 K-th Number Time Limit: 20000MS   Memory Limit: 65536K Total Submissions: 37130   Accepted: 11974 Case Time Limit: 2000MS Description You are working for Macrohard company in data structures department. After failing

POJ 2104 划分树模板题

给出n,m n个数字 m次询问,每次询问(l,r)区间的第k小的数 划分树模板 mark一下 #include "stdio.h" #include "string.h" #include "algorithm" using namespace std; int a[100010],as[100010]; int tree[20][100010];// 记录第i层元素序列 int sum[20][100010];// 记录第i层的1~j划分到左子

poj 2104 划分树模板

划分树的模板题. 1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 using namespace std; 5 6 const int N = 100001; 7 int tree[20][N]; 8 int sum[20][N]; 9 int as[N]; 10 11 void build( int p, int l, int r ) 12 { 13 int mid = ( ( l

划分树模板+模板题--hdu4251

题目链接:点击进入 划分树解决的是快速求区间中第k大值的问题,算法的主要思想是基于线段树和快排的划分方法,可以实现在logn时间内求出任意区间的第k大值.下面这份代码是基于hud4251的一份模板. 代码如下: #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int maxn=100000+1000; in

POJ2104 K-th Number 划分树 模板题啊

/*Source Code Problem: 2104 User: 96655 Memory: 14808K Time: 1282MS Language: G++ Result: Accepted Source Code*/ #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<vector> #include<stack>

hdu 2665 划分树模板题(可作为模板)

Kth number Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 6951    Accepted Submission(s): 2214 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The fi