HDU 2665(主席树,无修改第k小)

Kth number

                                                Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
                                                                        Total Submission(s): 10682    Accepted Submission(s): 3268

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 (n, m <=
100000), indicates the number of integers in the sequence and the number
of the quaere.
The second line contains n integers, describe the sequence.
Each of following m lines contains three integers s, t, k.
[s, t] indicates the interval and k indicates the kth big number in interval [s, t]

Output

For each test case, output m lines. Each line contains the kth big number.

Sample Input

1

10 1

1 4 2 3 5 6 7 8 9 0

1 3 2

Sample Output

2

Source

HDU男生专场公开赛——赶在女生之前先过节(From WHU)

垃圾主席树  浪费我时间

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cctype>
 5 #include<cmath>
 6 #include<cstring>
 7 #include<map>
 8 #include<stack>
 9 #include<set>
10 #include<vector>
11 #include<algorithm>
12 #include<string.h>
13 #define ll long long
14 #define LL unsigned long long
15 using namespace std;
16 const int INF=0x3f3f3f3f;
17 const double eps=0.0000000001;
18 const int N=100000+10;
19 struct node{
20     int left,right;
21     int val;
22 }tree[N*40];
23 int cnt;
24 int a[N],b[N];
25 int root[N];
26 int build(int l,int r){
27     int pos=++cnt;
28     tree[pos].val=0;
29     if(l==r)return pos;
30     int mid=(l+r)>>1;
31     tree[pos].left=build(l,mid);
32     tree[pos].right=build(mid+1,r);
33     return pos;
34 }
35 void update(int pre,int &now,int x,int l,int r){
36     tree[++cnt]=tree[pre];
37     now=cnt;
38     tree[now].val++;
39     if(l==r)return;
40     int mid=(l+r)>>1;
41     if(x<=mid){
42         update(tree[pre].left,tree[now].left,x,l,mid);
43     }
44     else{
45         update(tree[pre].right,tree[now].right,x,mid+1,r);
46     }
47
48 }
49 int query(int L,int R,int k,int l,int r){
50     if(l==r) return l;
51     int mid=(l+r)>>1;
52     int sum=tree[tree[R].left].val-tree[tree[L].left].val;
53     if(k<=sum){
54         return query(tree[L].left,tree[R].left,k,l,mid);
55     }
56     else{
57         return query(tree[L].right,tree[R].right,k-sum,mid+1,r);
58     }
59
60 }
61 int main()
62 {
63     int t;
64     scanf("%d",&t);
65     while(t--){
66         memset(root,0,sizeof(root));
67         memset(a,0,sizeof(a));
68         memset(b,0,sizeof(b));
69         int n,m;
70         scanf("%d%d",&n,&m);
71         cnt=0;
72         for(int i=1;i<=n;i++) {
73             scanf("%d",&a[i]);
74             b[i]=a[i];
75         }
76         sort(b+1,b+1+n);
77         int tt = unique(b+1,b+1+n)-b-1;
78         for(int i=1;i<=n;i++) {
79             a[i]=lower_bound(b+1,b+1+tt,a[i])-b;//二分找到a[i]的位置
81             update(root[i-1],root[i],a[i],1,tt);//root[i-1]表示上一个版本的线段树
82         }
83         for(int i=1;i<=m;i++) {
84             int l,r,k;
85             scanf("%d%d%d",&l,&r,&k);
86             int ans=query(root[l-1],root[r],k,1,tt); //ans是第k个数的位置
87             printf("%d\n", b[ans]);//因为询问的是哪个数,所以要b[ans]
88         }
89     }
90     return 0;
91 }
时间: 2024-08-07 06:51:50

HDU 2665(主席树,无修改第k小)的相关文章

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

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

poj 2104主席树求区间第k小

POJ - 2104 题意:求区间第k小 思路:无修改主席树 AC代码: #include "iostream" #include "iomanip" #include "string.h" #include "stack" #include "queue" #include "string" #include "vector" #include "set&

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];

主席树|求区间第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 ==

[POJ2104]K-th Number(主席树,静态区间k小)

题目链接:http://poj.org/problem?id=2104 题意:给一个数列,求给定区间第k小的数是多少. 思路:可以按照数字出现的次数为值建立线段树,每插入一个数字就维护一棵线段树,这样求某个区间(比如求[x,y]区间内)的第k小时就可以二分了.当tree[tree[x].l].sum - tree[tree[y].l].sum >= k时去查左儿子,tree[tree[x].l].sum - tree[tree[y].l].sum < k时去查右儿子.数据大,所以要离散化后再做

luogu P3834 【模板】可持久化线段树 1(主席树)| 静态第k小问题^&amp;

题目描述 如题,给定 nnn 个整数构成的序列,将对于指定的闭区间查询其区间内的第 kkk 小值. 输入格式 第一行包含两个正整数 n,mn,mn,m,分别表示序列的长度和查询的个数. 第二行包含 nnn 个整数,表示这个序列各项的数字. 接下来 mmm 行每行包含三个整数 l,r,k l, r, kl,r,k , 表示查询区间 [l,r][l, r][l,r] 内的第 kkk 小值. 输出格式 输出包含 kkk 行,每行一个整数,依次表示每一次查询的结果 莫队+树状数组:O(nsqrt(n)l

洛谷.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 5919 主席树(区间不同数的个数 + 区间第k大)

Sequence II Time Limit: 9000/4500 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 849    Accepted Submission(s): 204 Problem Description Mr. Frog has an integer sequence of length n, which can be denoted as a1,a2,?