玲珑杯#20 造物主的戒律

来源:互联网 发布:网络传输器 编辑:程序博客网 时间:2024/06/05 00:59

题目链接
题意给一个序列每次询问给l,r,x,k1,k2,每次查询区间中小于等于x的所有数字里面第k1小的值以及大于x的所有数字里面第k2小的值,如果不存在,输出-1
每次输出两个数,对于每个数如果不存在,则单独输出-1
主席树模板题,找出≤x的个数P,然后查询区间第k1 , k2+P小的数字。

#include<cmath>#include<algorithm>#include<cstring>#include<string>#include<set>#include<map>#include<time.h>#include<cstdio>#include<vector>#include<list>#include<stack>#include<queue>#include<iostream>#include<stdlib.h>using namespace std;#define  LONG long longconst int   INF=0x3f3f3f3f;const LONG  MOD=1e9+ 7;const double PI=acos(-1.0);#define clrI(x) memset(x,-1,sizeof(x))#define clr0(x) memset(x,0,sizeof x)#define clr1(x) memset(x,INF,sizeof x)#define clr2(x) memset(x,-INF,sizeof x)#define EPS 1e-10#define lson  l , mid , rt<< 1#define rson  mid + 1 ,r , (rt<<1)+1#define root 1, n , 1const int MAXN = 4e5 ;struct Tree{    int l, r ;    int val ;}tree[MAXN *30+ 30];int N , n ;int a[400100] ;int Root[400100] ;int tot = 0;int num[400100] ;void Push_up(int rt ){    tree[rt].val = tree[tree[rt].l].val + tree[tree[rt].r].val ;}int Build(int l, int r){    int rt = tot ++ ;    if(l == r)    {        tree[rt].val = 0 ;        return rt ;    }    int mid = (l + r) / 2;    tree[rt].l = Build(l , mid ) ;    tree[rt].r = Build(mid + 1, r) ;    Push_up(rt) ;    return rt ;}int  Hash(){    sort(a + 1, a +N+1 ) ;    return unique(a +1 , a + N +1 ) - a - 1;}int Update(int l ,int r , int rt , int x){    tot ++ ;    int now = tot ;    tree[now] = tree[rt] ;    if(l ==r )    {        tree[now].val ++ ;        return now;    }    int mid = ( l + r ) / 2;    if( x <= a[mid])        tree[now].l = Update(l , mid , tree[now].l ,x) ;    else        tree[now].r = Update(mid + 1, r , tree[now].r , x) ;    Push_up( now ) ;    return now  ;}int Que1( int l , int r , int R_rt ,int L_rt ,  int k ){    if(  ( l == r) )        return a[l];    int mid = (l +r ) / 2;    if(k > tree[tree[R_rt].l].val - tree[tree[L_rt].l].val )        return Que1(mid+1 ,r , tree[R_rt].r,tree[L_rt].r , k - tree[tree[R_rt].l].val + tree[tree[L_rt].l].val  ) ;    else        return Que1(l , mid ,tree[R_rt].l, tree[L_rt].l , k ) ;}int Que2(int l ,int r ,int R_rt , int L_rt , int x){    if(l == r)    {        if(a[l] <= x)            return tree[R_rt].val - tree[L_rt].val ;        return 0 ;    }    int mid = (l + r) / 2;    if(a[mid] >= x)        return Que2(l , mid , tree[R_rt].l , tree[L_rt].l , x)  ;    else return tree[tree[R_rt].l].val - tree[tree[L_rt].l].val  + Que2(mid + 1 , r , tree[R_rt].r , tree[L_rt].r , x ) ;}int main(){    int m ;    scanf("%d%d",&N ,&m) ;        tot = 0 ;        for(int i =1 ; i <= N ;++ i)            scanf("%d",&a[i]),num[i] = a[i] ;        n = Hash() ;        int now = 0 ;        Root[0] = Build(1 , n );        int p ;        for(int i = 1;i<= N ; ++ i)            Root[i] = Update(1 , n , Root[i-1] , num[i] ) ;        int K1,K2 ;        int l , r ;        int x ;        int len ;        int res1 , res2 ;        while(m --)        {            scanf("%d%d%d%d%d",&l,&r,&x,&K1, &K2) ;            int P = Que2(1 , n ,Root[r] , Root[l-1]  , x) ;            len = r - l + 1;            res1 = -1 , res2 = -1 ;            if(P >= K1 && K1 != 0)                res1 = Que1(1,n,Root[r],Root[l-1] , K1) ;            if( len - P >= K2&& K2 != 0)                res2 = Que1(1 , n ,Root[r] , Root[l-1] , K2 + P ) ;            printf("%d %d\n",res1,res2) ;        }    return 0 ;}
原创粉丝点击