原题:http://codeforces.com/contest/484/problem/E
题解:要求[l,r]中长度为k的子序列最小值最大。通过分析可以发现,k长的子序列不好求,类似于TJOI2016排序的那一题,二分一个值mid,将所有大于等于mid的都给1,其余都给0,只要查询给定区间最长连读1的长度就好了。尝试用一下线段树,需要对每一个值都建一颗线段树,同时还要不停的修改,这样显然是不好的。不妨将给的数组排序,很容易看出前一颗和后一颗只有一条链不一样,这其实就是主席树。所以先排序,然后一个一个加进主席中,就可以找到>=mid的01序列了,然后就可以快乐的二分了。
在求最长连续1的长度时的技巧,用结构体重载+法符号可以比较省事的合并左右子树
#include<bits/stdc++.h>
#define mid (l+r)/2
using namespace std;
const int N=1e5+10;
const int M=30;
const int MAXN=N*M;
struct node{int a,b;}a[N];
struct data{//要求最长连续1的序列长度重载一下+ 相当于两段的合并
int len,mm,lm,rm;
data(){len=mm=rm=lm=0;}
data(int L,int a,int b,int c){
len=L;mm=a;lm=b;rm=c;
}
friend data operator + (const data &x,const data &y){
int len=x.len+y.len;
int mm=max(x.mm,max(y.mm,x.rm+y.lm));
int lm=x.lm;if(lm==x.len) lm+=y.lm;
int rm=y.rm;if(rm==y.len) rm+=x.rm;
return (data){len,mm,lm,rm};
}
}tt[MAXN];
int mm[MAXN],lm[MAXN],rm[MAXN],L[MAXN],R[MAXN];
int T[N];
int n,m,tot;
inline int rd(){
int x=0;int f=1;char s=getchar();
while(!isdigit(s)) f=(s=='-'?-1:f),s=getchar();
while(isdigit(s)) x=(x<<1)+(x<<3)+s-'0',s=getchar();
return x*f;
}
bool cmp(node x, node y){
return x.a==y.a?x.b<y.b:x.a>y.a;
}
inline void upd(int rt){
tt[rt]=tt[L[rt]]+tt[R[rt]];
}
int build(int l,int r){
int rt=++tot;
if(l==r) {
tt[rt]=(data){1,0,0,0};return rt;
}else{
L[rt]=build(l,mid);
R[rt]=build(mid+1,r);
}
upd(rt);
return rt;
}
int update(int pre,int l,int r,int x){
int rt=++tot;
tt[rt]=tt[pre];L[rt]=L[pre];R[rt]=R[pre];
if(l==r) {
tt[rt]=(data){1,1,1,1};return rt;
}else{
if(x<=mid) L[rt]=update(L[pre],l,mid,x);
else R[rt]=update(R[pre],mid+1,r,x);
}
upd(rt);
return rt;
}
data query(int now,int l,int r,int x,int y){
if(x<=l && r<=y) return tt[now];
data ans=(data){0,0,0,0};
if(x<=mid) ans=ans+query(L[now],l,mid,x,y);
if(mid<y) ans=ans+query(R[now],mid+1,r,x,y);
return ans;
}
int query(int L,int R,int k){
int l=1;int r=n;
while(l<=r){
if(query(T[mid],1,n,L,R).mm>=k) r=mid-1;//a中降序排序
else l=mid+1;
}
return r+1;
}
int main(){
n=rd();
for(int i=1;i<=n;i++){
a[i].a=rd();a[i].b=i;
}
sort(a+1,a+n+1,cmp);
tot=0;
T[0]=build(1,n);//建成01主席树
for(int i=1;i<=n;i++) T[i]=update(T[i-1],1,n,a[i].b);
m=rd();
for(int i=1;i<=m;i++){
int x=rd();int y=rd();int k=rd();
printf("%d\n",a[query(x,y,k)].a);
}
return 0;
}