题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=3473


★没想到划分树里面也可以加东西,wcsl


题意:

给你一个由n个数组成的序列,有m次询问,每次询问给你一个区间(l,r)让你输出 x和这个区间的每一个数的差的绝对值 的求和 的最小值,x为任意数


思路:

这个x可以是排序后的区间的最居中的值:

我们把这个区间上的数想象为数轴上的点,当为奇数个时:
★这里的xn代表的是第n个点到x的距离
图很丑,将就一下嘛~ 黑圈和红圈分别代表区间的点 和 x值代表的点
上面是红圈在第三个点时的情况,下面是红圈在其它地方的情况(红线代表距离

很清楚的看到,下面的红线距离比上面正好多了一个x3,所以当点数为奇数时x的值越靠近中间时 总值是越小的(可以多画几个试试,我数学不行 只会大概证明一下啦 )
当为偶数个时同理,差不多, 不过x可以再中间两个点以及这两个点之间
但是为了统一奇数偶数的情况,我们不妨取题目已经给的点上

划分树:

设查询区间为(l,r),我们找其中第 ( r - l + 1 )/2+1 大的数当做x
那么我们通过划分树就可以找到x,但是怎么求最小值呢?

求最小值:

在区间里,作为中间值,x一定有ln个在它左边的数,rn个在它右边的数 ln+rn=y-x+1
如果我们知道,它左边的数的和sum1 和它右边的数的和sum2 那问题就简单了 sum1+sum2=sum[y]-sum[x-1]
LL ans=ln*x-sum1+sum2-rn*x;
求ln和sum1的过程 要充分理解划分树的性质,我是看了半天的awa


代码:

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<stack>
#include<queue>
#include<map>
#include<vector>
#include<set>
#define ls k<<1,l,mid
#define rs k<<1|1,mid+1,r
#define r(x) read(x)
using namespace std;
typedef long long LL;
const int N=1e5+5;
const int M=1e3+5;
const int mod=1e9+7;
const int inf=0x7fffffff;
const double pi=acos(-1);
const double eps=1e-8;
template<class T>
inline void read(T &x)
{char c;x=1;while((c=getchar())<'0'||c>'9') if(c=='-') x=-1;T res=c-'0';while((c=getchar())>='0'&&c<='9') res=res*10+c-'0';x*=res;
}
LL sum[N];
LL ss[20][N];
int f[N];
int v[20][N];
int num[20][N];
LL sum1,sum2;
LL ln,rn;
void build(int l,int r,int dep)
{if(l==r) return ;int mid=(l+r)>>1;int res=(mid-l+1);for(int i=l;i<=r;i++) if(v[dep][i]<f[mid]) res--;int l1=l,l2=mid+1;for(int i=l;i<=r;i++){if(v[dep][i]<f[mid]){v[dep+1][l1++]=v[dep][i];ss[dep][i]=ss[dep][i-1]+v[dep][i];}else if(v[dep][i]==f[mid]&&res>0){v[dep+1][l1++]=v[dep][i];ss[dep][i]=ss[dep][i-1]+v[dep][i];res--;}else{v[dep+1][l2++]=v[dep][i];ss[dep][i]=ss[dep][i-1];}num[dep][i]=num[dep][l-1]+l1-l;}build(l,mid,dep+1);build(mid+1,r,dep+1);
}
int query(int l,int r,int dep,int x,int y,int k)
{//    cout<<l<<' '<<r<<endl;if(x==y) return v[dep][x];int mid=(l+r)>>1;int cnt=num[dep][y]-num[dep][x-1];if(k<=cnt){int l1=l+num[dep][x-1]-num[dep][l-1];int r1=l1+cnt-1;return query(l,mid,dep+1,l1,r1,k);}else{sum1+=ss[dep][y]-ss[dep][x-1];ln+=num[dep][y]-num[dep][x-1];int r2=y+num[dep][r]-num[dep][y];int l2=r2-(y-x-cnt);return query(mid+1,r,dep+1,l2,r2,k-cnt);}
}
int main()
{int t; r(t);int cas=0;while(t--){int n,m;r(n);for(int i=1;i<=n;i++){r(f[i]);v[0][i]=f[i];sum[i]=sum[i-1]+f[i];}sort(f+1,f+n+1);build(1,n,0);r(m);printf("Case #%d:\n",++cas);while(m--){int a,b;r(a); r(b);a++; b++;sum1=sum2=0;ln=rn=0;int x=query(1,n,0,a,b,(b-a+1)/2+1);sum2=sum[b]-sum[a-1]-sum1;rn=b-a+1-ln;LL ans=ln*x-sum1+sum2-rn*x;
//            cout<<ln<<' '<<rn<<' '<<sum1<<' '<<sum2<<endl;cout<<ans<<endl;}cout<<endl;}return 0;
}

HDU 3473 Minimum Sum 【划分树】相关推荐

  1. hdu 3473 Minimum Sum 划分树

    http://acm.hdu.edu.cn/showproblem.php?pid=3473 对于xl,xl+1--xr,使得[xi-x]和最小,显然x应当为其中的中位数.中位数可以通过求K大数解决, ...

  2. HDU-3743 Minimum Sum,划分树模板

    Minimum Sum 被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数. 题意:找一个数使得这个数和区间内所有数的差的绝对值最小.输出最小值. 开始用线段树来了一发果断T了,然后各种 ...

  3. HDU 3473 Minimum Sum

    HDU_3437 比较容易证明,x应该取区间的中位数,于是问题就转化成了求[l,r]区间内大小排第(l+r)/2+1的数,然后将和计算出来即可. 求区间的中位数可以用划分树来实现,但是和却不可以在求得 ...

  4. hdu 2665 Kth number(划分树模板)

    http://acm.hdu.edu.cn/showproblem.php?pid=2665 [ poj 2104 2761 ]  改变一下输入就可以过 http://poj.org/problem? ...

  5. HDU 4417 Super Mario(划分树)

    Super Mario Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  6. hdu 2665 Kth number 划分树

    求区间第k大元素的值, 看代码的注释. #include<cstring> #include<cstdio> #include<iostream> #include ...

  7. HDU - 6955 Xor sum tire树 + 贪心

    传送门 文章目录 题意: 思路: 题意: 给你一个数列aaa,你需要找出来一个长度最小且左端点最靠前的区间,使其异或和≥k\ge k≥k. n≤1e5,0≤ai,k<230n\le1e5,0\l ...

  8. hdu 4417 Super Mario 划分树+二分

    http://acm.hdu.edu.cn/showproblem.php?pid=4417 题意: 给定一个长度为n的序列,求区间[L,R]中小于h的个数: 思路: 分三种情况: 1:如果该区间最小 ...

  9. HDU - 4825 Xor Sum(字典树)

    题目链接:点击查看 题目大意:给出n个数组成的数组,再给出m个询问,每次询问给出一个x,要求从数组中选出一个k,使得k^x的值最大 题目分析:字典树求异或值最大的模板题,对于n个数直接insert到字 ...

最新文章

  1. data的值 如何初始化vue_vue data恢复初始化数据的实现方法
  2. Pandas的学习(3.DataFrame的创建方法和三种索引方法(iloc、loc、values)以及切片)
  3. [PHP]对Json字符串解码返回NULL的一般解决方案
  4. 将时间格式的字符串转换成日期类型浏览器兼容解决方案
  5. 51单片机——硬件基础
  6. 汇编取值运算符OFFSET,SEG,LEA和属性运算符PTR
  7. ERROR 2002 (HY000): mysql
  8. SVN安装以及使用教程
  9. 地理信息系统教程(汤国安)——重点总结
  10. php smarty入门,smarty教程专题
  11. html文字冒险游戏,小说新类型介绍之文字冒险游戏
  12. 微信开发--IOS微信端confirm以及alert去掉网址的方法
  13. 游戏对战平台搭建要选什么服务器
  14. cs231n-LSTM_Captions
  15. 漫漫挨踢路,淡淡感想录
  16. 【统计学】基本Stata使用手册(1):基本操作
  17. Azure: Azure AD(For Development)的使用
  18. 云计算专业运维工程师所需要的知识技术
  19. 二阶龙格库塔公式推导_[常微分方程的数值解法系列五] 龙格-库塔(RK4)法
  20. video 满屏显示_HTML5 video播放器全屏(fullScreen)实现的方法

热门文章

  1. 【奶奶看了也不会】AI绘画 Mac安装stable-diffusion-webui绘制AI妹子保姆级教程
  2. sql中将字符串数字转换成数字
  3. upupoo服务器维护中是什么情况,upupoo用不了怎么办-解决upupoo打不开的方法 - 河东软件园...
  4. 中国汽车使用保险行业市场供需与战略研究报告
  5. 笔杆网试用---感官体验篇一
  6. Linux命令详解(2) – mv
  7. python抓取酷我MV
  8. 使用ST-LINK下载STM32程序
  9. IOS开发之——第一个IOS应用
  10. 大富翁11 V1.0.7 官方中文绿色免安装版