hdu3473区间条件极值 - 区间 差的绝对值 之和的最小
Posted tea-egg
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu3473区间条件极值 - 区间 差的绝对值 之和的最小相关的知识,希望对你有一定的参考价值。
题目传送门//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:\n",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\n", ans);
cout<<endl;
以上是关于hdu3473区间条件极值 - 区间 差的绝对值 之和的最小的主要内容,如果未能解决你的问题,请参考以下文章
hdu5289 Assignment (区间查询最大值最小值,st算法...)
HDU6621 K-th Closest Distance 第 k 小绝对值(主席树(统计范围的数有多少个)+ 二分 || 权值线段树+二分)