1. 程式人生 > >可持久化線段樹 區間第k大

可持久化線段樹 區間第k大

getchar() AI 多少 lin urn pri 長度 != register

2018-04-04 http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1175 一個長度為N的整數序列,編號0 - N - 1。進行Q次查詢,查詢編號i至j的所有數中,第K大的數是多少。 例如: 1 7 6 3 1。i = 1, j = 3,k = 2,對應的數為7 6 3,第2大的數為6。 Input
第1行:1個數N,表示序列的長度。(2 <= N <= 50000)
第2 - N + 1行:每行1個數,對應序列中的元素。(0 <= S[i] <= 10^9)
第N + 2行:1個數Q,表示查詢的數量。(2 <= Q <= 50000)
第N + 3 - N + Q + 2行:每行3個數,對應查詢的起始編號i和結束編號j,以及k。(0 <= i <= j <= N - 1,1 <= k <= j - i + 1)
Output
共Q行,對應每一個查詢區間中第K大的數。
Input示例
5
1
7
6
3
1
3
0 1 1
1 3 2
3 4 2
Output示例
7
6
1

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<cctype>
using namespace std;
inline int gi(){int d=0;char c=getchar();while(!isdigit(c))c=getchar();
while
(isdigit(c)){d=(d<<3)+(d<<1)+c-0;c=getchar();}return d;} const int N=50005; const int M=2000005; struct QUE{ int l,r,i,k; }q[M]; bool cmp1(QUE aa,QUE bb){ return aa.r<bb.r; } int sm[M<<2],ls[M],rs[M],rt[M],tot; int a[N],san[N],num[N],ans[N],cnt; int n,Q; #define gem int mi=(l+r)>>1 void
gai(int old,int &o,int l,int r,int P,int C){ o=++tot; ls[o]=ls[old];rs[o]=rs[old];sm[o]=sm[old]+C; if(l==r)return; gem; if(P<=mi)gai(ls[o],ls[o],l,mi,P,C); else gai(rs[o],rs[o],mi+1,r,P,C);//?? } int qur(int old,int o,int l,int r,int k){ if(l==r)return l; int sum=sm[rs[o]]-sm[rs[old]]; gem; if(sum<k)return qur(ls[old],ls[o],l,mi,k-sum); else return qur(rs[old],rs[o],mi+1,r,k); } #define rep(xx,yy,zz) for(xx=yy;xx<=zz;++xx) int main(){ register int i,j; n=gi(); rep(i,1,n){ a[i]=gi();san[i]=a[i]; } sort(san+1,san+n+1); rep(i,1,n) if(i==1||san[i]!=san[i-1]) num[++cnt]=san[i]; Q=gi(); rep(i,1,Q){ q[i].i=i;q[i].l=gi()+1;q[i].r=gi()+1;q[i].k=gi(); } sort(q+1,q+Q+1,cmp1); j=1; rep(i,1,n){ int x=lower_bound(num+1,num+cnt+1,a[i])-num; gai(rt[i-1],rt[i],1,cnt,x,1); for(;q[j].r==i;++j){ ans[q[j].i]=qur(rt[q[j].l-1],rt[i],1,cnt,q[j].k); } } rep(i,1,Q){ printf("%d\n",num[ans[i]]); } return 0; }



可持久化線段樹 區間第k大