Minimum Sum

被这个题坑了一下午,原来只需找一个最中间的数即可,我以为是平均数。

题意:找一个数使得这个数和区间内所有数的差的绝对值最小。输出最小值。

开始用线段树来了一发果断T了,然后各种优化依然T不断。于是只能用划分树做。不过,其实熟悉划分树也是模板水题。

打一个前缀和,然后这个数肯定是这个区间从大到小排在最中间的。所以查询一遍将小于中间这个数的和加起来,然后得到将小于这个数的个数。分为前半段和后半段分别加起来即可。

手残将一个地方写错了,然后无限RE。。。。最后一行一行debug,心塞。

ll sum[N],lsum[20][N];
int  tree[20][N],a[N],t_l[20][N];
void build(int l,int r,int id)
{if(l==r) return ;int mid=(l+r)/2;int same=mid-l+1;for(int i=l;i<=r;i++) if(tree[id][i]<a[mid]) same--;int lp=l,rp=mid+1;
for(int i=l;i<=r;i++){if(tree[id][i]<a[mid]){tree[id+1][lp++]=tree[id][i];lsum[id][i]=lsum[id][i-1]+tree[id][i];}else if(tree[id][i]==a[mid]&&same>0){tree[id+1][lp++]=tree[id][i],same--;lsum[id][i]=lsum[id][i-1]+tree[id][i];}else{tree[id+1][rp++]=tree[id][i];lsum[id][i]=lsum[id][i-1];}t_l[id][i]=t_l[id][l-1]+lp-l;}build(l,mid,id+1);build(mid+1,r,id+1);
}
ll isum;
int num;
int find(int l,int r,int k,int L,int R,int id)
{if(l==r) return tree[id][l];int mid=(L+R)/2;int cnt=t_l[id][r]-t_l[id][l-1];if(cnt>=k){int newl=L+t_l[id][l-1]-t_l[id][L-1];int newr=newl+cnt-1;return  find(newl,newr,k,L,mid,id+1);}else{num+=cnt;isum+=lsum[id][r]-lsum[id][l-1];int newr=r+t_l[id][R]-t_l[id][r];int newl=newr-(r-l-cnt);return  find(newl,newr,k-cnt,mid+1,R,id+1);}
}
int main()
{int t,n,m;scanf("%d",&t);int t1=t;while(t--){scanf("%d",&n);memset(sum,0,sizeof(sum));for(int i=0; i<20; i++) tree[i][0]=t_l[i][0]=lsum[i][0]=0;for(int i=1;i<=n;i++){scanf("%d",&tree[0][i]);a[i]=tree[0][i];sum[i]=sum[i-1]+a[i];}sort(a+1,a+n+1);build(1,n,0);scanf("%d",&m);printf("Case #%d:\n",t1-t);while(m--){int l,r;scanf("%d%d",&l,&r);if(l==r) puts("0");else{l++,r++;int k=(r-l)/2+1;num=0;//得到小于中间这个数的个数isum=0;//得到小于中间这个数的和ll x=find(l,r,k,1,n,0);printf("%I64d\n",(ll)x*(num-(r-l+1-num))+sum[r]-sum[l-1]-isum-isum);}}puts("");}return 0;
}

注意 long long 。

转载于:https://www.cnblogs.com/nyist-TC-LYQ/p/7208109.html

HDU-3743 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 2665 Kth number(划分树模板)

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

  3. poj2104(划分树模板)

    poj2104 题意 给出一个序列,每次查询一个区间,要求告诉这个区间排序后的第k个数. 分析 划分树模板,O(mlogn). 建树.根据排序之后的数组,对于一个区间,找到中点的数,将整个区间分为左右 ...

  4. HDU 4417 Super Mario(划分树)

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

  5. HDU 3473 Minimum Sum 【划分树】

    题目来源:http://acm.hdu.edu.cn/showproblem.php?pid=3473 ★没想到划分树里面也可以加东西,wcsl 题意: 给你一个由n个数组成的序列,有m次询问,每次询 ...

  6. HDU 3473 Minimum Sum

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

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

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

  8. hdu 2665 Kth number 划分树

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

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

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

最新文章

  1. 计算机领域收费sci期刊,计算机领域收费sci期刊 - 百度学术
  2. 上海大学计算机技术 a股,这所上海大学短时间就成为211,实力强劲却不为人知,适合捡漏...
  3. 计算机优化英语,英语对计算机专业的重要性及如何提高英语水平
  4. Spring-Aop-XML实现
  5. FD.io VPP 使用场景-用例
  6. 把python37添加到环境变量配置_linux设置python环境变量 分类: python ...
  7. python打包exe_Python | 用Pyinstaller打包发布exe应用
  8. 转:Web页面通过URL地址传递参数常见问题及检测方法
  9. vba连接mysql前的准备_VBA连接MYSQL数据库方法及案例
  10. 2019.8.10小结
  11. C#基础编程——简介及基础语法
  12. 名茶事典——【贡(寿)眉】
  13. Hive学习使用一周感悟
  14. 手动关联endnote20和wps
  15. 使用范例调教ChatGPT
  16. angular路由模拟微信页面切换和页面之间的传值
  17. python中文文本情感分析
  18. HTML网页设计基础笔记 • 【第1章 HTML5基础】
  19. Codeforces 1183E/H Subsequences dp
  20. vue 项目ztree 异步加载树

热门文章

  1. bzoj 4753: [Jsoi2016]最佳团体
  2. 翻译 | 关键CSS和Webpack: 减少阻塞渲染的CSS的自动化解决方案
  3. mybatis查询如何返回ListMap类型数据
  4. Recover Binary Search Tree,恢复二叉排序树
  5. 如何关闭360自定义错误页面
  6. java.util.Queue用法
  7. 图的基本算法实现(邻接矩阵与邻接表两种方法)
  8. DPDK之makefile编译选项修改和gdb调试(三)
  9. leetcode算法题--最长数对链
  10. leetcode算法题--三角形最小路径和