K-th Number POJ - 2104
K-th Number POJ - 2104
That is, given an array a[1...n] of different integer numbers, your program must answer a series of questions Q(i, j, k) in the form: "What would be the k-th number in a[i...j] segment, if this segment was sorted?"
For example, consider the array a = (1, 5, 2, 6, 3, 7, 4). Let the question be Q(2, 5, 3). The segment a[2...5] is (5, 2, 6, 3). If we sort this segment, we get (2, 3, 5, 6), the third number is 5, and therefore the answer to the question is 5.
Input
The second line contains n different integer numbers not exceeding 109 by their absolute values --- the array for which the answers should be given.
The following m lines contain question descriptions, each description consists of three numbers: i, j, and k (1 <= i <= j <= n, 1 <= k <= j - i + 1) and represents the question Q(i, j, k).
Output
Sample Input
- 7 3
- 1 5 2 6 3 7 4
- 2 5 3
- 4 4 1
- 1 7 3
Sample Output
- 5
- 6
- 3
Hint
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<sstream>
- #include<cmath>
- #include<stack>
- #include<cstdlib>
- #include <vector>
- #include<queue>
- using namespace std;
- #define ll long long
- #define llu unsigned long long
- #define INF 0x3f3f3f3f
- #define PI acos(-1.0)
- const int maxn = 1e5+;
- const int mod = 1e9+;
- int n,q,m,tot;
- int a[maxn],t[maxn],T[maxn],lson[maxn*],rson[maxn*],c[maxn*];
- void Init_hash()
- {
- for(int i=;i<=n;i++)
- t[i] = a[i];
- sort(t+,t++n);
- m = unique(t+,t++n)-t-;
- }
- int build(int l,int r)
- {
- int root = tot++;
- c[root] = ;
- if (l != r)
- {
- int mid = (l+r) >> ;
- lson[root] = build(l,mid);
- rson[root] = build(mid+,r);
- }
- return root;
- }
- int Hash(int x)
- {
- return lower_bound(t+,t++m,x)-t;
- }
- int update(int root,int pos,int val)
- {
- int newroot = tot ++,tmp = newroot;
- c[newroot] = c[root] + val;
- int l = ,r = m;
- while(l <r)
- {
- int mid = (l+r)>>;
- if(pos <= mid)
- {
- lson[newroot] = tot++;
- rson[newroot] = rson[root];
- newroot = lson[newroot];
- root = lson[root];
- r = mid;
- }
- else
- {
- rson[newroot] = tot ++;
- lson[newroot] = lson[root];
- newroot = rson[newroot];
- root = rson[root];
- l = mid + ;
- }
- c[newroot] = c[root] + val;
- }
- return tmp;
- }
- int query(int left_root,int right_root,int k)
- {
- int l = ,r = m;
- while(l < r)
- {
- int mid = (l+r) >> ;
- if(c[lson[left_root]] - c[lson[right_root]] >= k)
- {
- r = mid;
- left_root = lson[left_root];
- right_root = lson[right_root];
- }
- else
- {
- l = mid + ;
- k -= c[lson[left_root]] - c[lson[right_root]];
- left_root = rson[left_root];
- right_root = rson[right_root];
- }
- }
- return l;
- }
- int main()
- {
- scanf("%d%d",&n,&q);
- tot = ;
- for(int i=;i<=n;i++)
- scanf("%d",&a[i]);
- Init_hash();
- T[n+] = build(,m);
- for(int i=n;i;i--)
- {
- int pos = Hash(a[i]);
- T[i] = update(T[i+],pos,);
- }
- while(q--)
- {
- int l,r,k;
- scanf("%d%d%d",&l,&r,&k);
- printf("%d\n",t[query(T[l],T[r+],k)]);
- }
- }
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- #include<stack>
- #include<cstdlib>
- #include<queue>
- #include<set>
- #include<string.h>
- #include<vector>
- #include<deque>
- #include<map>
- using namespace std;
- #define INF 0x3f3f3f3f3f3f3f3f
- #define inf 0x3f3f3f3f
- #define eps 1e-4
- #define bug printf("*********\n")
- #define debug(x) cout<<#x"=["<<x<<"]" <<endl
- typedef long long LL;
- typedef long long ll;
- const int maxn = 2e5 + ;
- const int mod = ;
- int n,m,a[maxn],root[maxn],cnt;
- vector<int>v;
- struct node{
- int l,r,sum;
- }T[maxn * ];
- int getid(int x) {
- return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
- }
- void update(int l,int r,int &x,int y,int pos) {
- T[++cnt] = T[y],T[cnt].sum ++,x = cnt;
- if(l == r) return;
- int mid = (l + r) / ;
- if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos);
- else update(mid + ,r,T[x].r,T[y].r,pos);
- }
- int query(int l,int r,int x,int y,int k) {
- if(l == r) return l;
- int mid = (l + r) / ;
- int sum = T[T[y].l].sum - T[T[x].l].sum;
- if(sum >= k) return query(l,mid,T[x].l,T[y].l,k);
- else return query(mid + ,r,T[x].r,T[y].r,k - sum);
- }
- void init() {
- cnt = ;
- memset(root,,sizeof root);
- }
- int main()
- {
- init();
- scanf("%d %d",&n,&m);
- for (int i = ; i <= n; ++i) {
- scanf("%d",&a[i]);
- v.push_back(a[i]);
- }
- sort(v.begin(),v.end());
- v.erase(unique(v.begin(),v.end()),v.end());
- for (int i = ; i <= n; ++i)
- update(,n,root[i],root[i - ],getid(a[i]));
- for (int i = ; i <= m; ++i) {
- int x,y,k;
- scanf("%d %d %d",&x, &y, &k);
- printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
- }
- }
- #include<cstdio>
- #include<iostream>
- #include<algorithm>
- #include<cstring>
- #include<cmath>
- #include<stack>
- #include<cstdlib>
- #include<queue>
- #include<set>
- #include<string.h>
- #include<vector>
- #include<deque>
- #include<map>
- using namespace std;
- #define INF 0x3f3f3f3f3f3f3f3f
- #define inf 0x3f3f3f3f
- #define eps 1e-4
- #define bug printf("*********\n")
- #define debug(x) cout<<#x"=["<<x<<"]" <<endl
- typedef long long LL;
- typedef long long ll;
- const int maxn = 2e5 + ;
- const int mod = ;
- int n,m,a[maxn],root[maxn],cnt;
- /*
- root:代表每个历史版本线段树的根节点位置
- cnt:用作开辟新的树节点
- */
- vector<int>v;
- struct node{
- int l,r,sum;
- }T[maxn * ]; //线段树区间统计,sum代表在这个区间数的个数
- int getid(int x) { //获取离散数组后的下标
- return lower_bound(v.begin(),v.end(),x) - v.begin() + ;
- }
- /*
- update函数:
- y代表前一棵树的节点位置,x是后面的节点位置
- */
- void update(int l,int r,int &x,int y,int pos) {
- //&x 引用节点指针扩展新节点
- T[++cnt] = T[y],T[cnt].sum ++,x = cnt; //新开节点,将需要修改的树节点复制到新开辟节点,改变自己的sum
- if(l == r) return;
- int mid = (l + r) / ;
- if(mid >= pos) update(l,mid,T[x].l,T[y].l,pos); //节点左边
- else update(mid + ,r,T[x].r,T[y].r,pos); //节点右边
- }
- int query(int l,int r,int x,int y,int k) {
- if(l == r) return l;
- int mid = (l + r) / ;
- int sum = T[T[y].l].sum - T[T[x].l].sum; //两颗线段树sum做差
- if(sum >= k) return query(l,mid,T[x].l,T[y].l,k); //如果当前的结点个数sum比k要大的话,说明第k大的结点在左子树当中,就去遍历左子树
- else return query(mid + ,r,T[x].r,T[y].r,k - sum); //如果当前的结点个数sum比k要小的话,说明第k大的结点在右子树当中,而左子树的结点个数是sum个,那就去找右子树中的第k-sum的数
- }
- void init() {
- cnt = ;
- memset(root,,sizeof root);
- }
- int main()
- {
- init();
- scanf("%d %d",&n,&m);
- for (int i = ; i <= n; ++i) {
- scanf("%d",&a[i]);
- v.push_back(a[i]); //离散化数组
- }
- sort(v.begin(),v.end()); //离散化数组
- v.erase(unique(v.begin(),v.end()),v.end()); //离散化数组
- for (int i = ; i <= n; ++i) {
- update(, n, root[i], root[i - ], getid(a[i]));
- }
- for (int i = ; i <= m; ++i) {
- int x,y,k;
- scanf("%d %d %d",&x, &y, &k);
- printf("%d\n",v[query(,n,root[x - ],root[y],k) - ]);
- }
- }
K-th Number POJ - 2104的更多相关文章
- K-th Number Poj - 2104 主席树
K-th Number Poj - 2104 主席树 题意 给你n数字,然后有m次询问,询问一段区间内的第k小的数. 解题思路 这个题是限时训练做的题,我不会,看到这个题我开始是拒绝的,虽然题意清晰简 ...
- 主席树 【权值线段树】 && 例题K-th Number POJ - 2104
一.主席树与权值线段树区别 主席树是由许多权值线段树构成,单独的权值线段树只能解决寻找整个区间第k大/小值问题(什么叫整个区间,比如你对区间[1,8]建立一颗对应权值线段树,那么你不能询问区间[2,5 ...
- K-th Number POJ - 2104 划分树
K-th Number You are working for Macrohard company in data structures department. After failing your ...
- HDU 2665.Kth number-可持久化线段树(无修改区间第K小)模板 (POJ 2104.K-th Number 、洛谷 P3834 【模板】可持久化线段树 1(主席树)只是输入格式不一样,其他几乎都一样的)
Kth number Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total ...
- AC日记——K-th Number poj 2104
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 52348 Accepted: 17985 Ca ...
- hdu 2665 Kth number (poj 2104 K-th Number) 划分树
划分树的基本功能是,对一个给定的数组,求区间[l,r]内的第k大(小)数. 划分树的基本思想是分治,每次查询复杂度为O(log(n)),n是数组规模. 具体原理见http://baike.baidu. ...
- POJ 2104&HDU 2665 Kth number(主席树入门+离散化)
K-th Number Time Limit: 20000MS Memory Limit: 65536K Total Submissions: 50247 Accepted: 17101 Ca ...
- poj 2104 K-th Number 主席树+超级详细解释
poj 2104 K-th Number 主席树+超级详细解释 传送门:K-th Number 题目大意:给出一段数列,让你求[L,R]区间内第几大的数字! 在这里先介绍一下主席树! 如果想了解什么是 ...
- poj 2104 K-th Number(主席树,详细有用)
poj 2104 K-th Number(主席树) 主席树就是持久化的线段树,添加的时候,每更新了一个节点的线段树都被保存下来了. 查询区间[L,R]操作的时候,只需要用第R棵树减去第L-1棵树就是区 ...
随机推荐
- form中onsubmit的使用
form 中的onsubmit在点submit按钮时被触发,如果return false;则结果不会被提交到action中去(也就是提交动作不会发生),如果不返回或者返回true,则执行提交动作.(& ...
- web 单例 多例
单例多例需要搞明白两个问题:1. 什么是单例多例:2. 如何产生单例多例:3. 为什么要用单例多例4. 什么时候用单例,什么时候用多例:1. 什么是单例多例:所谓单例就是所有的请求都用一个对象来处理, ...
- jQuery学习笔记(四)
动画效果 显示和隐藏效果 无动画效果 显示:show() 隐藏:hide() <!DOCTYPE html> <html lang="en"> <he ...
- 少写代码帮你模块化方法 & 运动框架 & 简化轮播图
模块化就是通过每一个js里封装一个方法:用exports将他输出, 在下一个js用require的方法加载js时就会将方法输出.然后在主页面引入require.js; 模块化基本写法: define( ...
- spring mvc <mvc;resources>
spring mvc 的<mvc;resources mapping="***" location="***">标签是在spring3.0.4出现的 ...
- MAC MAMP install yaf
Yaf doesn't support PHP 5.6! You may see this: Warning: PHP Startup: yaf: Unable to initialize modul ...
- mif文件生成方法
mif文件就是存储器初始化文件,即memory initialization file,用来配置RAM或ROM中的数据.常见生成方法: Quartus自带的mif编辑器生成 mif软件生成 高级编程语 ...
- ubuntu 自动启动程序
首先打开终端ctrl + alt + t sudo -i 输入密码:ubuntu chmod 777 /etc/rc.local 打开 vi /etc/rc.local 按 i 键进入输入 ...
- php使用GD库实现图片水印和缩略图——给图片添加图片水印
今天呢,就来学习一下在php中使用PD库来实现对图片水印的文字水印方法,不需要PS哦! 首先,准备素材 (1)准备一张图片 (2)准备一张水印(最好是透明的,即背景是白色底) (3)准备一中字体(在电 ...
- [Git] Create a new repository on the command line
echo "# xxx" >> README.md git init git add README.md git commit -m "first commi ...