静态区间第K大

<a target=_blank href="http://poj.org/problem?id=2104" target="_blank"><span style="font-size:24px;">POJ 2104</span></a>

POJ 2761

做法好多,主席树,划分树,离线处理(曼哈顿最小生成树?)+BST(Treap or Splay or SBT),貌似分治+BIT也可以,不过懒得搞了。

以后复习模板时用得上。

主席树:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100010;
struct Node{
	int l,r,w;
}tr[N*20];
int a[N],b[N],rank[N],root[N],sz;
void ins(int &i,int l,int r,int x){
	tr[++sz]=tr[i];i=sz;
	tr[i].w++;
	if(l==r)return;
	int m=l+r>>1;
	if(x<=m)ins(tr[i].l,l,m,x);
	else ins(tr[i].r,m+1,r,x);
}
int query(int i,int j,int l,int r,int k){
	if(l==r)return l;
	int m=l+r>>1;
	int tmp=tr[tr[j].l].w-tr[tr[i].l].w;
	if(k<=tmp)return query(tr[i].l,tr[j].l,l,m,k);
	else  return query(tr[i].r,tr[j].r,m+1,r,k-tmp);
}
inline bool cmp(int i,int j){
	return a[i]<a[j];
}
int main(){
	int n,m;scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);rank[i]=i;
	}
	sort(rank+1,rank+1+n,cmp);
	for(int i=1;i<=n;i++)b[rank[i]]=i;
	for(int i=1;i<=n;i++){
		root[i]=root[i-1];
		ins(root[i],1,n,b[i]);
	}
	int x,y,k;
	while(m--){
		scanf("%d%d%d",&x,&y,&k);
		int tmp=query(root[x-1],root[y],1,n,k);
		printf("%d\n",a[rank[tmp]]);
	}
	return 0;
}


你可能感兴趣的:(静态区间第K大)