HDU3473Minimum Sum
来源:互联网 发布:java jdk 1.7 for mac 编辑:程序博客网 时间:2024/05/20 22:40
//这题是利用划分树的题目;
//每层多加了一个变量lsum【dep】【i】表示该层放入左边的元素之和;
//之后在求中位数即第(b - a + 1) / 2大的数时,顺便利用lsum【dep】【i】求出中位数左边数之和,之后求出中位数右边数字之和;
//之后就显而易见了
#include<stdio.h>#include<algorithm>const int MAXN = 100100;int n, q, tcase;int order[MAXN], tree[25][MAXN], left[25][MAXN];__int64 lsum[25][MAXN], sum[MAXN], lsu;void Build(int x, int y, int dep){ if(x == y) return ; int mid = (x + y) >> 1; int lmid = mid - x + 1; for(int i = x; i <= y; i++) if(tree[dep][i] < order[mid]) lmid -- ; int ls = x, rs = mid + 1; __int64 ans = 0; for(int i = x; i <= y; i++) { if(tree[dep][i] < order[mid]) { tree[dep + 1][ls++] = tree[dep][i]; ans += tree[dep][i]; } else if(tree[dep][i] > order[mid]) { tree[dep + 1][rs++] = tree[dep][i]; } else if(lmid > 0) { tree[dep + 1][ls++] = tree[dep][i]; ans += tree[dep][i]; lmid --; } else { tree[dep + 1][rs++] = tree[dep][i]; } left[dep][i] = ls - x; lsum[dep][i] = ans;//包括本身 } Build(x, mid, dep + 1); Build(mid + 1, y, dep + 1);}void Init(){ scanf("%d", &n); sum[0] = 0; for(int i = 1; i <= n; i++) { scanf("%d", &order[i]); tree[0][i] = order[i]; sum[i] = sum[i-1] + order[i]; } std::sort(order + 1, order + 1 + n); Build(1, n, 0);}int Query(int x, int y, int dep, int l, int r, int k){ if(x == y) { lsu += tree[dep][x]; return tree[dep][x]; } __int64 ls, lss; int s, ss, mid = (x + y) >> 1; ; if(l == x) ss = 0, lss = 0; else ss = left[dep][l-1], lss = lsum[dep][l-1]; s = left[dep][r] - ss, ls = lsum[dep][r] - lss; if(s >= k) return Query(x, mid , dep + 1, x + ss, x + left[dep][r] - 1, k); else { lsu += ls; return Query(mid + 1, y, dep + 1, mid + 1 + (l - x - ss), mid + 1 + (r - x - left[dep][r]), k - s); }}void Solve(int cur){ int a, b, num, tmp; __int64 ans; scanf("%d", &q); printf("Case #%d:\n", cur); for(int i = 1; i <= q; i++) { scanf("%d%d", &a, &b); num = b - a + 1; lsu = 0;//中位数左边总和 tmp = Query(1, n, 0, a + 1, b + 1, (num + 1)/ 2);//中位数的值 ans = sum[b + 1] - sum[a] - lsu - lsu; if(num & 1) ans += tmp; printf("%I64d\n", ans); } putchar('\n');}int main(){ scanf("%d", &tcase); for(int i = 1; i <= tcase; i++) { Init(); Solve(i); } return 0;}
- HDU3473Minimum Sum
- hdu3473Minimum Sum【划分树sum维护】
- Sum
- sum
- sum
- Sum
- Sum
- Sum
- sum
- Sum
- sum
- Sum
- sum
- Sum
- sum
- Sum Sum Sum
- HDU5150 Sum Sum Sum
- HDU - 5150 Sum Sum Sum
- 一些数字推理题
- 关于if语句的使用简单举例,如果输入的数字不在有效范围内可继续输入 .cpp
- dwz js 框架的小记
- 杭电 1002
- 第九周-分段函数求解(switsh语句)
- HDU3473Minimum Sum
- 杭电 1003
- android系统信息(内存、cpu、sd卡、电量、版本)获取
- 杭电 1004
- 将命令结果赋值给一个变量
- 杭电 1005
- DSG realsync 源端抽取lob字段报错
- utf8转gbk,去掉繁体字符
- 杭电 1006