POJ2104 K-th Number 不带修改的主席树 线段树

http://poj.org/problem?id=2104

给定一个序列,求区间第k小

通过构建可持久化的点,得到线段树左儿子和右儿子的前缀和(前缀是这个序列从左到右意义上的),然后是一个二分的get操作。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<algorithm>
 4 #include<cstring>
 5 #include<cmath>
 6 #define LL long long
 7 const LL maxn=100010;
 8 using namespace std;
 9 int n,m;
10 struct node{
11     int lc,rc,sum;
12 }t[maxn*20];int tot;
13 struct nod{
14     int x,id;
15 }a[maxn];
16 int rk[maxn]={},rt[maxn]={};
17 bool mcmp(nod aa,nod bb){return aa.x<bb.x;}
18 void insert(int &x,int l,int r,int num){
19     t[++tot]=t[x]; ++t[tot].sum;x=tot;//cout<<t[x].sum<<endl;
20     if(l==r)return;
21     int mid=(r+l)/2;
22     if(num<=mid)insert(t[x].lc,l,mid,num);
23     else insert(t[x].rc,mid+1,r,num);
24 }
25 int getit(int x,int y,int k,int l,int r){
26     if(l==r)return l;
27     int z=t[t[y].lc].sum-t[t[x].lc].sum;
28     int mid=(r+l)/2;
29     if(k<=z)return getit(t[x].lc,t[y].lc,k,l,mid);
30     else return getit(t[x].rc,t[y].rc,k-z,mid+1,r);
31 }
32 int main(){
33     while(~scanf("%d%d",&n,&m)){
34         tot=0;
35         for(int i=1;i<=n;i++){scanf("%d",&a[i].x);a[i].id=i;}
36         sort(a+1,a+1+n,mcmp);
37         for(int i=1;i<=n;i++) rk[a[i].id]=i;
38         for(int i=1;i<=n;i++){rt[i]=rt[i-1]; insert(rt[i],1,n,rk[i]);}
39         int x,y,k;
40         for(int i=1;i<=m;i++){
41             scanf("%d%d%d",&x,&y,&k);
42             printf("%d\n",a[getit(rt[x-1],rt[y],k,1,n)].x);
43         }
44     }
45     return 0;
46 }

原文地址:https://www.cnblogs.com/137shoebills/p/8710192.html

时间: 2024-11-08 04:43:58

POJ2104 K-th Number 不带修改的主席树 线段树的相关文章

【poj1901-求区间第k大值(带修改)】树状数组套主席树

901: Zju2112 Dynamic Rankings Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 7025  Solved: 2925[Submit][Status][Discuss] Description 给定一个含有n个数的序列a[1],a[2],a[3]--a[n],程序必须回答这样的询问:对于给定的i,j,k,在a[i],a[i+1],a[i+2]--a[j]中第k小的数是多少(1≤k≤j-i+1),并且,你可以改变一些a[i]

Luogu Dynamic Ranking (带修改的主席树)

带修改的主席树: 原本的主席树是维护了一个线段树前缀. 那么前缀有没有想到什么东西? 树状数组\(Bits\)是不是很 ...... ? 那么现在,我们用树状数组套主席树,不就可以实现带修改的可持久化了吗. 具体来说 \(T[1]维护rt[1]\) , \(T[2]维护rt[1].rt[2]\) , \(T[3]维护rt[3]\) ...... 就与树状数组是一样的. 那么现在,两个具体的操作: 修改: 修改需要修改\(logN\)棵主席树,将涉及修改节点的\(log\)个主席树先删后加点即可.

带修改的主席树

普通主席树认为是前缀套线段树,那么这就是树状数组套线段树 前缀区间由原来的一个前缀一个线段树变成BIT组成的几棵线段树一起 每个线段树维护的还是离散排序后的数列 每个节点也相当于一个主席树,我觉得更像是线段树,但是修改的时候用到了主席树的方法,就是在原来的基础上修改(只不过这些原来的都不保存) add操作要修改一些主席树 sum操作要加一些主席树的区间和 外层的BIT是为了处理询问区间,内层是为了找k值 kth时候要把用到的主席树提出了,每个都往左往右 代码(未提交过) // // main.c

BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树

https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节不要出现zz错误. 这道题修改的数量比较少可以写莫队,但是如果修改数量多或者是特别极限的数据大概是不行的吧. 1 #include<iostream> 2 #include<cstdio> 3 #include<algorithm> 4 #include<cstrin

【算法系列学习】线段树vs树状数组 单点修改,区间查询 [kuangbin带你飞]专题七 线段树 A - 敌兵布阵

https://vjudge.net/contest/66989#problem/A 单点修改,区间查询 方法一:线段树 http://www.cnblogs.com/kuangbin/archive/2011/08/15/2139834.html 1 #include<iostream> 2 #include<cstdio> 3 #include<string> 4 #include<cstring> 5 #include<cmath> 6 #

[kuangbin带你飞]专题七 线段树

A - 敌兵布阵 HDU - 1166 C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就是要监视这些工兵营地的活动情况.由于采取了某种先进的监测手段,所以每个工兵营地的人数C国都掌握的一清二楚,每个工兵营地的人数都有可能发生变动,可能增加或减少若干人手,但这些都逃不过C国的监视. 中央情报局要研究敌人究竟演习什么战术,所以Tidy要随时向Derek汇报某一段连续的工兵营地一共有多少

不带修改的主席树

#include<map> #include<stdio.h> #include<string.h> #include<vector> #include<algorithm> #include<iostream> using namespace std; const int maxn=2e5*19; int vis[maxn]; int a[maxn],b[maxn]; struct node1 { int l,r,sum; }T[m

BZOJ 4026 dC Loves Number Theory 分块+十字链表/可持久化线段树

题目大意:给定一个序列,多次询问某段区间乘积的φ值对1000777的模 我竟然卡过去了233333 将序列分块,记录fi,j表示第i块左端点到第j个点中出现的所有质数p的p?1p之积 每次询问[x,y],首先取出[x,y]区间内所有数的积,然后乘上fst,y(其中st是x后面第一个块端点所在块) 现在还剩[x,l[st]]部分没有统计 由于106以内的数分解得到的不同的质因数最多只有7个,因此暴力枚举零碎部分的质数即可 现在对于每个质数我们需要判断是否出现过 我们只需要判断这个质数下一次出现的位

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小

少年,想学带修改主席树吗 | BZOJ1901 带修改区间第k小 有一道题(BZOJ 1901)是这样的:n个数,m个询问,询问有两种:修改某个数/询问区间第k小. 不带修改的区间第k小用主席树很好写,不会的同学可以看一下这个. 加上修改怎么做呢?我们可以用数学老师成天讲的类比思想: 可以发现,不修改的区间k小问题中,每加入一个原序列中的数,对应的主席树在上一个的基础上进行修改,而查询的时候用右端点主席树减去左端点左边的主席树.这样的操作就像是维护前缀和:每次加入一个元素的时候,sum[i] =