• hdu 4471 区间条件统计 区间 不超过 x 的元素的个数


    题目传送门//res tp hdu

    目的

    对长度为n的区间,m次询问,每次提供一个区间两端点与一个值x,求区间内不超过x的元素个数

    n 1e5
    m 1e5
    ai [1,1e9] (i∈[1,n])
    多测

    数据结构与……?

    划分树 + 二分查找

    分析

    建树0(nlogn)
    单次查询第k小,需O(logn)
    蛮力枚举区间内所有元素,查看是否大于x,需O(nlogn),m次询问,总O(mnlogn),显然会超时。

    考虑以二分x的方式枚举出不超过x的最大上界只需O(mlogxlogn)。这种方法是可接受的。

    #include<iostream>
    #include<algorithm>
    using namespace std;
    const int L = 100010;
    int tr[18][L],cnt[18][L],n,m,sor[L];
    
    void build(int de,int l,int r){
    	if(l == r) return;
    	int mi = (l + r)>>1;
    	int scnt = mi - l + 1;
    	int M = sor[mi];
    	for(int i = l;i<=r;++i) if(tr[de][i] < M) scnt--;
    	int pl = l,pr = mi + 1;
    	for(int i = l,cntl = 0;i<=r;++i){
    		int num = tr[de][i];
    		if(num < M ||(num == M && scnt > 0)){
    			if(num == M) --scnt;
    			++cntl;
    			tr[de+1][pl++] = num;
    		}
    		else tr[de+1][pr++] = num;
    		cnt[de][i] = cntl;
    	}
    	build(de+1,l,mi);
    	build(de+1,mi+1,r);
    }
    int query(int de,int L,int R,int l,int r,int k){
    	if(L == R) return tr[de][L];
    	int mi = (L + R)>>1;
    	int left = 0,cnt_in_left = cnt[de][r];
    	if(L != l){
    		left = cnt[de][l-1];
    		cnt_in_left -= left;
    	}
    	if( k <= cnt_in_left ){
    		int newl = L + left;
    		int newr = newl + cnt_in_left - 1;
    		return query(de+1,L,mi,newl,newr,k);
    	}
    	else{
    		int a = l - L - left;
    		int b = r - l + 1 - cnt_in_left;
    		int newl = mi + 1 + a;
    		int newr = newl + b - 1;
    		return query(de+1,mi+1,R,newl,newr,k - cnt_in_left);
    	}
    }
    int Q(int l,int r,int h){
    	int lo = 1,hi = r - l + 1;
    	while(lo <= hi){
    		int mi = (lo + hi)>>1;
    		int M =query(0,1,n,l,r,mi);
    		if(h < M ) hi = mi-1;
    		else lo = mi + 1;
    	}
    	return --lo;
    }
    int main(){
    	int T,icase = 1,l,r,h,ans;
    	scanf(" %d",&T);
    	while(T--){
    		scanf(" %d %d",&n,&m);
    		for(int i = 1;i<=n;++i){
    			scanf(" %d",&sor[i]);
    			tr[0][i] = sor[i];
    		}
    		sort(sor+1,sor+1+n);
    		build(0,1,n);
    		printf("Case %d:
    ",icase++);
    		while(m--){
    			scanf(" %d %d %d",&l,&r,&h);
    			ans = Q(l+1,r+1,h);
    			printf("%d
    ",ans);
    		}
    	}
    }
    
    
    
    
  • 相关阅读:
    java源码之HashMap和HashTable的异同
    java源码之HashMap
    进制转换
    java基本数据类型及其包装类
    java实例化对象的五种方法
    20 栈的压入、弹出序列
    19 包含min函数的栈
    18 顺时针打印矩阵(记忆,常忘记)
    16 树的子结构(这题多复习)
    15合并两个排序的链表
  • 原文地址:https://www.cnblogs.com/tea-egg/p/11248877.html
Copyright © 2020-2023  润新知