poj 2104主席树求区间第k小

POJ - 2104

题意:求区间第k小

思路:无修改主席树

AC代码:

#include "iostream"
#include "iomanip"
#include "string.h"
#include "stack"
#include "queue"
#include "string"
#include "vector"
#include "set"
#include "map"
#include "algorithm"
#include "stdio.h"
#include "math.h"
#pragma comment(linker, "/STACK:102400000,102400000")
#define bug(x) cout<<x<<" "<<"UUUUU"<<endl;
#define mem(a,x) memset(a,x,sizeof(a))
#define step(x) fixed<< setprecision(x)<<
#define mp(x,y) make_pair(x,y)
#define pb(x) push_back(x)
#define ll long long
#define endl ("\n")
#define ft first
#define sd second
#define lrt (rt<<1)
#define rrt (rt<<1|1)
using namespace std;
const ll mod=1e9+7;
const ll INF = 1e18+1LL;
const int inf = 1e9+1e8;
const double PI=acos(-1.0);
const int N=1e5+100;

int ls[N*20],rs[N*20],rt[N],sum[N*20],cnt;
int n,m,ran[N];

void creat(int &cur, int l, int r){
    cur=++cnt;
    sum[cur]=0;
    if(l==r) return;
    int mid=l+r>>1;
    creat(ls[cur], l, mid);
    creat(rs[cur], mid+1, r);
}

void update(int &cur, int l, int r, int p, int last){
    cur=++cnt;
    ls[cur]=ls[last];
    rs[cur]=rs[last];
    sum[cur] = sum[last]+1;
    if(l==r) return;
    int mid=l+r>>1;
    if(p<=mid) update(ls[cur], l, mid, p, ls[cur]);
    else update(rs[cur], mid+1, r, p, rs[cur]);
}

int query(int cur_l, int cur_r, int l, int r, int k){
    if(l==r) return l;
    int t=sum[ls[cur_r]]-sum[ls[cur_l]];
    int mid=l+r>>1;
    if(t>=k) return query(ls[cur_l], ls[cur_r], l, mid, k);
    else return query(rs[cur_l], rs[cur_r], mid+1, r, k-t);
}

struct Node{
    int id, x;
    bool friend operator< (Node a, Node b){
        return a.x<b.x;
    }
    bool friend operator== (Node a, Node b){
        return a.x==b.x;
    }
}a[N];
int main(){
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    while(cin>>n>>m){
        for(int i=1; i<=n; ++i){
            cin>>a[i].x; a[i].id=i;
        }
        sort(a+1,a+1+n); cnt=0;
        int sz=n;//unique(a+1,a+1+n) - (a+1); ///cout<<sz<<endl;
        for(int i=1; i<=sz; ++i) ran[a[i].id]=i;
        creat(rt[0], 1, n);
        for(int i=1; i<=n; ++i){ //cout<<ran[i]<<endl;
            update(rt[i], 1, n, ran[i], rt[i-1]);
        }
        while(m--){
            int l,r,k; cin>>l>>r>>k;
            cout<<a[query(rt[l-1], rt[r], 1, sz, k)].x<<endl;
        }
    }
    return 0;
}
时间: 2024-12-27 21:59:19

poj 2104主席树求区间第k小的相关文章

主席树|求区间第k小模板

主席树 学了主席树,用来求区间上的第k小 写一下自己整理后的模板 求区间第k小 #include<bits/stdc++.h> using namespace std; //求区间第k小 const int maxn = 500010; struct node{ int v,lc,rc; }T[maxn * 21]; int n,m; int root[maxn]; int e; void insert(int pre,int cur,int pos,int l,int r){ if(l ==

[poj 2104]主席树+静态区间第k大

题目链接:http://poj.org/problem?id=2104 主席树入门题目,主席树其实就是可持久化权值线段树,rt[i]维护了前i个数中第i大(小)的数出现次数的信息,通过查询两棵树的差即可得到第k大(小)元素. #include<cstdio> #include<vector> #include<algorithm> using namespace std; #define lson(i) node[i].lson #define rson(i) node

poj 2401 划分树 求区间第k大的数

题目:http://poj.org/problem?id=2104 划分树待我好好理解下再写个教程吧,觉得网上的内容一般,,, 模板题: 贴代码: #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; #define CLR(a) memset(a,0,sizeof(a)) const int MAXN = 1000

HDU 5919 - Sequence II (2016CCPC长春) 主席树 (区间第K小+区间不同值个数)

HDU 5919 题意: 动态处理一个序列的区间问题,对于一个给定序列,每次输入区间的左端点和右端点,输出这个区间中:每个数字第一次出现的位子留下, 输出这些位子中最中间的那个,就是(len+1)/2那个. 思路: 主席树操作,这里的思路是从n到1开始建树.其他就是主席树查询区间第K小,计算区间不同值个数. #include <algorithm> #include <iterator> #include <iostream> #include <cstring&

SPOJ 10628 Count on a tree(Tarjan离线LCA+主席树求树上第K小)

COT - Count on a tree #tree You are given a tree with N nodes.The tree nodes are numbered from 1 to N.Each node has an integer weight. We will ask you to perform the following operation: u v k : ask for the kth minimum weight on the path from node u 

主席树(区间第k小的数)

题目链接: https://www.luogu.org/problem/P3834 首先要离散化,然后主席树模板. 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #define mid (l+r)/2 5 using namespace std; 6 7 const int N = 200010; 8 int n, q, m, cnt = 0; 9 int a[N], b[N], T[N];

HDOJ题目4417 Super Mario(划分树求区间比k小的个数+二分)

Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 3313    Accepted Submission(s): 1548 Problem Description Mario is world-famous plumber. His "burly" figure and amazing jumping a

洛谷.3834.[模板]可持久化线段树(主席树 静态区间第k小)

题目链接 //离散化后范围1~cnt不要错 #include<cstdio> #include<cctype> #include<algorithm> //#define gc() getchar() #define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) const int N=2e5+5,MAXIN=2e6; int n,m,A[N],ref[N],cn

hdu 2665 可持久化线段树求区间第K大值(函数式线段树||主席树)

http://acm.hdu.edu.cn/showproblem.php?pid=2665 Problem Description Give you a sequence and ask you the kth big number of a inteval. Input The first line is the number of the test cases. For each test case, the first line contain two integer n and m (