poj2104

网上都说要用什么划分树。。。但是我特么不会啊。。so~~~~10s多卡过去了
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<string>
#include<cstdlib>
#include<map>
#include<algorithm>
using namespace std;
#define max_n 1000005
const int B=1000;
int A[max_n],I[max_n],J[max_n],K[max_n];
int nums[max_n];
int n,m;
vector<int> bucket[max_n/B];
void solve(){
    for(int i=0;i<n;i++){
        bucket[i/B].push_back(A[i]);
        nums[i]=A[i];
    }
    sort(nums,nums+n);
    for(int i=0;i<n/B;i++){
        sort(bucket[i].begin(),bucket[i].end());
    }
    for(int i=0;i<m;i++){
        int l=I[i],r=J[i],k=K[i];
        int lb=-1,ub=n-1;
        while(ub-lb>1){
            int md=(lb+ub)/2;
            int x=nums[md];
            int tl=l-1,tr=r,c=0;
            while(tl<tr && tl%B!=0)if(A[tl++]<=x)c++;
            while(tl<tr && tr%B!=0)if(A[--tr]<=x)c++;
            while(tl<tr){
                int b=tl/B;
                c+=upper_bound(bucket[b].begin(),bucket[b].end(),x)-bucket[b].begin();
                tl+=B;
            }
            if(c>=k)ub=md;
            else lb=md;
        }
        printf("%d\n",nums[ub]);
    }
}
int main()
{
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)
        scanf("%d",&A[i]);
        for(int i=0;i<m;i++)
        scanf("%d%d%d",&I[i],&J[i],&K[i]);
        solve();
    return 0;
}

今天重新做了一次。。。用了一发归并树,6000+ms再次飘过

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<list>
#include<map>
#include<algorithm>
#define max_n 1000000
#define lc l,y,index<<1
#define rc y+1,r,index<<1|1
using namespace std;
vector<int> dat[(1<<18)-1];
int A[max_n],I[max_n],J[max_n],K[max_n],nums[max_n];
int n,m;
void build(int l,int r,int index){
    int y=(l+r)/2;
  //  printf("l== %d r== %d\n",l,r);
    if(r==l){
        dat[index].push_back(A[l]);
        return ;
    }
    else{
        build(lc);
        build(rc);
        //printf("%d\n",r-l+1);
        dat[index].resize(r-l+1);
        merge(dat[index<<1].begin(),dat[index<<1].end(),dat[index<<1|1].begin(),dat[index<<1|1].end(),dat[index].begin());
    }
}
int query(int L,int R,int x,int l,int r,int index){
    //printf("L== %d R== %d l== %d r== %d\n",L,R,l,r);
    int y=(l+r)/2;
    if(L<=l && R>=r){
        return upper_bound(dat[index].begin(),dat[index].end(),x)-dat[index].begin();
    }
    else if(R<=y)
    return query(L,R,x,lc);
    else if(L>y)
    return query(L,R,x,rc);
    else{
        int a=query(L,y,x,lc);
        int b=query(y+1,R,x,rc);
        return a+b;
    }
}
void solve(){
    for(int i=0;i<m;i++){
        int l=I[i],r=J[i],k=K[i];
    int ub=n,lb=0,md,c=0,x;
    while(ub-lb>1){
        md=(ub+lb)/2;
        x=nums[md];
        c=query(l,r,x,1,n,1);
      //  printf("x== %d c== %d ",x,c);
        if(c>=k)
        ub=md;
        else lb=md;
      //  printf("lb== %d ub== %d\n",lb,ub);
        }
    printf("%d\n",nums[ub]);
    }
}
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++){
        scanf("%d",&A[i]);
        nums[i]=A[i];
        }
    sort(nums+1,nums+n+1);
    for(int i=0;i<m;i++)
    scanf("%d%d%d",&I[i],&J[i],&K[i]);
    build(1,n,1);
    solve();
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值