F - Assassin’s Creed

来源:互联网 发布:淘宝不能用 编辑:程序博客网 时间:2024/05/01 05:14

求区间[L,R]内小于等于k的数的个数。

划分树+二分

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define N 100005
int n;
int arr[N];//原数据,下标从1 开始
int sortedPos[N];//排序后
int lfnum[50][N];//元素所在区间的当前位置进入左孩子的元素的个数


int val[50][N];//记录第k 层当前位置的元素的值
bool cmp(const int &x,const int &y) {
    return arr[x]<arr[y];
}
void build(int l,int r,int d) {
    if(l==r) return;
    int mid=(l+r)>>1,p=0;
    for(int i=l; i<=r; i++) {
        if(val[d][i]<=mid) {
            val[d+1][l+p]=val[d][i];
            lfnum[d][i]=++p;
        } else {
            lfnum[d][i]=p;
            val[d+1][mid+i+1-l-p]=val[d][i];
        }
    }
    build(l,mid,d+1);
    build(mid+1,r,d+1);
}
//求区间[s,e]第k 大的元素
int query(int s,int e,int k,int l=1,int r=n,int d=0) {
    if(l==r) return l;
    int mid=(l+r)>>1,ss,ee;
    ss=(s==l?0:lfnum[d][s-1]);
    ee=lfnum[d][e];
    if(ee-ss>=k) return query(l+ss,l+ee-1,k,l,mid,d+1);
    return query(mid+1+(s-l-ss),mid+1+(e-l-ee),k-(ee-ss),mid+1,r,d+1);
}


int bin_find(int k,int left,int right) {
    int l=1;
    int r=right-left+1;
    int mid=0;
    while(l<=r) {
        mid=(l+r)/2;
        if(arr[sortedPos[query(left,right,mid)]]<=k) {
            l=mid+1;
        } else {
            r=mid-1;
        }
    }
    return l-1;
}
int main() {
    int cas=1,m,l,r,k;
    int T;
    scanf("%d",&T);
    while(T--) {
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++) {
            scanf("%d",arr+i),sortedPos[i]=i;
        }
        sort(sortedPos+1,sortedPos+n+1,cmp);
        for(int i=1; i<=n; i++) {
            val[0][sortedPos[i]]=i;
        }
        build(1,n,0);
        printf("Case %d:\n",cas++);
        while(m--) {
            scanf("%d%d%d",&l,&r,&k);
            l++;
            r++;
            int mid=0;
            if(arr[sortedPos[query(l,r,r-l+1)]]<=k) {
                printf("%d\n",r-l+1);
                continue;
            }
            if(arr[sortedPos[query(l,r,1)]]>k) {
                printf("0\n");
                continue;
            }
            mid=bin_find(k,l,r);
            if(mid==0) {
                puts("0");
                continue;
            }
           // cout<<"**"<<mid<<endl;
            while(1) {
                int ans=arr[sortedPos[query(l,r,mid+1)]];
                if(ans==k) {
                    mid++;
                } else {
                    break;
                }
            }
            printf("%d\n", mid);
        }
    }
    return 0;
}
/*
1
10 10
0 5 2 7 5 4 3 8 7 7
2 8 6
3 5 0
1 3 1
1 9 4
0 1 0
3 5 5
5 5 1
4 6 3
1 5 7
5 7 3
*/

0 0