• hdu 3473 区间条件极值


    题目传送门//res tp hdu

    目的

    对长度为n的区间,给定q个子区间,求一x,使得区间内所有元素与x的差的绝对值之和最小。
    多测。
    n 1e5
    q 1e5
    ai [1,1e9] (i∈[1,n]);

    数据结构

    划分树

    tip

    该划分树维护的cnt并非元素所在区间内,该元素之前进入左子树的元素个数,而是整个区间内,该元素之前进入左子树的元素个数。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    
    const int L = 100000+50;
    typedef long long ll;
    int n,q;
    int tree[18][L];
    int cnt[18][L];
    ll sum[18][L],ans;
    int a[L],sorted[L];
    
    void build(int de,int l,int r){
    	if(l == r){
    		sum[de][l] = sum[de][l-1] + tree[de][l];return;
    	}
    	if(de == 0){
    		for(int i = 1;i<=r;++i)
    			tree[de][i] = a[i];
    	}
    	int mi=(l+r)>>1;
    	int scnt = mi - l + 1;
    	ll M = sorted[mi];
    	for(int i = l;i<=mi;++i) if(sorted[i] < M)
    		scnt--;
    	int pl = l,pr = mi + 1;
    	for(int i = l;i<=r;++i){
    		ll num =tree[de][i];
    		if(num == M){
    			if(scnt){
    				scnt--;
    				tree[de+1][pl++] = num;
    				cnt[de][i]++;
    			}
    			else
    				tree[de+1][pr++] = num;
    		}
    		else if(num < M){
    			tree[de+1][pl++] = num;
      			cnt[de][i]++;
    		}
    		else
    			tree[de+1][pr++] = num;
    		sum[de][i] = sum[de][i-1] + tree[de][i];
    		cnt[de][i] += cnt[de][i-1];
    	}
    	build(de+1,l,mi);
    	build(de+1,mi+1,r);
    }
    
    ll query(int de,int L,int R,int l,int r,int k){
    	if(L == R) return tree[de][L];
    
    	int mi = (L + R)>>1;
    	int lo1,lo2,hi1,hi2;
    	int CNT = cnt[de][r] - cnt[de][l-1];
    	lo1 = L + cnt[de][l-1] - cnt[de][L-1];
    	hi1 = L + cnt[de][r] - cnt[de][L-1] - 1;
    	lo2 = mi + 1 + l - L - cnt[de][l-1] + cnt[de][L-1];
    	hi2 = mi + 1 + r - L - cnt[de][r] + cnt[de][L-1];
    	if(k <= CNT){
    		if(hi2 >= lo2)
    			ans += sum[de+1][hi2] - sum[de+1][lo2-1];
    		return query(de+1,L,mi,lo1,hi1,k);
    	}
    	else{
    		if(hi1>=lo1)
    		ans -= sum[de+1][hi1] - sum[de+1][lo1-1];
    		return query(de+1,mi+1,R,lo2,hi2, k - CNT);
    	}
    }
    
    
    
    
    int main(){
    	int T,l,r;
    	int icase = 1;
    	scanf(" %d",&T);
    	while(T--){
    		scanf(" %d",&n);
    		memset(sum,0,sizeof(sum));
    		memset(cnt,0,sizeof(cnt));
    		for(int i = 1;i<=n;++i){
    			scanf(" %d",a + i);
    			sorted[i] = a[i];
    		}
    		sort(sorted+1,sorted+1+n);
    		build(0,1,n);
    		scanf(" %d",&q);
    		printf("Case #%d:
    ",icase++);
    		while(q--){
    			ans = 0;
    			scanf(" %d %d",&l,&r);
    			l++;r++;
    			ll t = query(0,1,n,l,r,(r - l)/2 + 1);
    			if((r-l)%2 == 1)
    				ans -= t;
    			printf("%lld
    ", ans);
    		}
    		cout<<endl;
    	}
    }
    
    
    
  • 相关阅读:
    正则函数及面向对象开发初识---day19
    正则计算器---day19
    正则表达式re模块---day18
    批量下载英雄联盟官网皮肤及打包
    zip压缩模块,tarfile压缩模块,包和模块,format格式化的复习--day17
    计算一个文件夹里面所有文件的大小---day17
    time模块,os操作系统及os模块和shutil模块用法---day16
    http请求方法
    cube.js
    http响应码
  • 原文地址:https://www.cnblogs.com/tea-egg/p/11247723.html
Copyright © 2020-2023  润新知