hdu 3473 Minimum Sum
2015-07-29 18:17
323 查看
[align=left]Problem Description[/align]
You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you some intervals [l, r]. For each interval, you need to find a number x to make
as small as possible!
[align=left]Input[/align]
The first line is an integer T (T <= 10), indicating the number of test cases. For each test case, an integer N (1 <= N <= 100,000) comes first. Then comes N positive integers x (1 <= x <= 1,000, 000,000) in the next line. Finally,
comes an integer Q (1 <= Q <= 100,000), indicting there are Q queries. Each query consists of two integers l, r (0 <= l <= r < N), meaning the interval you should deal with.
[align=left]Output[/align]
For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of
. Output a blank line after every test case.
[align=left]Sample Input[/align]
[align=left]Sample Output[/align]
题意:给你一个区间[l,r],要求sum|x-xi|(l<=i<=r)的最小值,其中x必须为xl,xl+1...xr中的一个数。
分析:值最小时x为序列的中位数,可以用划分树求得,sum|x-xi|=sum(x-xi)(xi<=x)+sum(xi-x)(xi>x),在划分树求中位数x的过程中可以计算出≤x的数(划分到左边)的个数sl和和suml,≥x的数(划分到右边)的个数sr和sumr,则ans=(sl-sr)*x+sumr-suml。
You are given N positive integers, denoted as x0, x1 ... xN-1. Then give you some intervals [l, r]. For each interval, you need to find a number x to make
as small as possible!
[align=left]Input[/align]
The first line is an integer T (T <= 10), indicating the number of test cases. For each test case, an integer N (1 <= N <= 100,000) comes first. Then comes N positive integers x (1 <= x <= 1,000, 000,000) in the next line. Finally,
comes an integer Q (1 <= Q <= 100,000), indicting there are Q queries. Each query consists of two integers l, r (0 <= l <= r < N), meaning the interval you should deal with.
[align=left]Output[/align]
For the k-th test case, first output “Case #k:” in a separate line. Then output Q lines, each line is the minimum value of
. Output a blank line after every test case.
[align=left]Sample Input[/align]
2 5 3 6 2 2 4 2 1 4 0 2 2 7 7 2 0 1 1 1
[align=left]Sample Output[/align]
Case #1: 6 4 Case #2: 0 0
题意:给你一个区间[l,r],要求sum|x-xi|(l<=i<=r)的最小值,其中x必须为xl,xl+1...xr中的一个数。
分析:值最小时x为序列的中位数,可以用划分树求得,sum|x-xi|=sum(x-xi)(xi<=x)+sum(xi-x)(xi>x),在划分树求中位数x的过程中可以计算出≤x的数(划分到左边)的个数sl和和suml,≥x的数(划分到右边)的个数sr和sumr,则ans=(sl-sr)*x+sumr-suml。
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; typedef long long LL; const int N = 101010; int sum[20] ,tr[20] ,sr ; LL lsum, rsum; LL lnum, rnum; LL ss[20] ; void build(int l, int r, int d) { for(int i=l; i<=r; i++) ss[d][i] = ss[d][i-1] + (LL)tr[d][i]; if(l == r) return; int mid = l + r >> 1, i, lp = l, rp = mid+1; int eqnum, tp=0; for(int i=l; i<=r; i++) if(tr[d][i] < sr[mid]) tp++; eqnum = mid-l+1-tp; tp = 0; for(i=l; i<=r; i++) { sum[d][i] = sum[d][i-1]; if(tr[d][i] < sr[mid]) tr[d+1][lp++] = tr[d][i], sum[d][i]++; else if(tr[d][i] == sr[mid] && tp < eqnum) tr[d+1][lp++] = tr[d][i], sum[d][i]++, tp++; else tr[d+1][rp++] = tr[d][i]; } build(l,mid,d+1); build(mid+1,r,d+1); } int query(int s, int t, int k, int l, int r, int d) { if(s == t) return tr[d][s]; int mid = l + r >> 1; int x = sum[d][s-1] - sum[d][l-1]; int y = sum[d][t] - sum[d][s-1]; if(y >= k) { rsum += ss[d+1][mid+s-l-x+t-s+1-y]-ss[d+1][s-l-x+mid]; rnum += (mid + s-l-x + t-s+1-y)-(s-l-x+mid+1) + 1; return query(l+x, l+x+y-1,k, l, mid, d+1); } lsum+=ss[d+1][l+x+y-1]-ss[d+1][l+x-1]; lnum+= (l+x+y-1) - (l+x) + 1; return query(s-l-x+mid+1, mid + s-l-x + t-s+1-y, k-y, mid+1, r, d+1); } int main() { //freopen("date.in","r",stdin); //freopen("date.out2","w",stdout); int i,j,k,m,n; int a,b,c; int T; int cas = 0; for(i=0; i<20; i++) sum[i][0] = tr[i][0] = ss[i][0] = 0; bool blank = false; scanf("%d",&T); while(T--) { printf("Case #%d:\n",++cas); scanf("%d",&n); for(i=1; i<=n; i++) scanf("%d",sr+i); for(i=1; i<=n; i++) tr[0][i] = sr[i]; sort(sr+1, sr+1+n); build(1,n,0); scanf("%d",&m); while(m--) { scanf("%d %d",&a,&b); a++,b++; if(a > b) swap(a,b); int mid = a+b>>1; k = mid-a+1; lsum = rsum = 0; lnum = rnum = 0; c = query(a,b,k,1,n,0); printf("%I64d\n",(lnum-rnum)*c+rsum-lsum); } puts(""); } return 0; }
相关文章推荐
- AndroidMaterialDesign动画之Activity Transitions
- error RC2108: expected numerical dialog constant
- 密钥验证登陆主机
- 黑马程序员--iOS--Objective-C基础 (面向对象)
- 促销价格 功能设计
- source、sh、bash、./执行脚本的区别
- 关于回调函数的个人理解
- 函数柯里化or not
- HTML5实现摇一摇
- 关于卫星RNSS与RDSS
- 运行时类型标识RTTI常见问题分析
- 如何查看Oracle数据库表空间大小(空闲、已使用),是否要增加表空间的数据文件
- shiro实现HasAnyPermission 标签效果
- RabbitMQ 快速入门
- 判断图片上传
- Maven零散笔记——常用配置(tomcat-maven-plugin)
- 并发管理器的工作原理 和 cmclean.sql的潜在危险
- The Podfile
- 手动创建UIWindow及UIWindowLevel的说明
- java中 Unicode和UTF-8的关系