HDU 3473 Minimum Sum 划分树
来源:互联网 发布:智慧猫儿童编程 编辑:程序博客网 时间:2024/05/14 02:25
有n个数,每次给出一段区间l,r,选出一个数X使得|X-Xi|(l<=i<=r)尽量小,X显然是中位数。此外还要得到区间和,这个可以在划分树递归的时候累加,当递归左子树的时候,可以加上所有大于中位数的数,递归右子树的时候可以减去所有小于中位数的数。
#include <cstdio>#include <cstring>#include <algorithm>using namespace std;typedef __int64 LL;const int maxn = 100010;int tree[20][maxn], toleft[20][maxn], a[maxn];LL sum[20][maxn];void build(int l, int r, int dep){ if(l == r) { sum[dep][l] = tree[dep][l]; return; } int m = (l+r) >> 1; int tol = m-l+1; for(int i = l; i <= r; i++) { if(tree[dep][i] < a[m]) tol--; sum[dep][i] = tree[dep][i]; if(i > l) sum[dep][i] += sum[dep][i-1]; } int L = l, R = m+1; for(int i = l; i <= r; i++) { if(tree[dep][i] < a[m]) tree[dep+1][L++] = tree[dep][i]; else if(tree[dep][i] == a[m] && tol > 0) { tree[dep+1][L++] = tree[dep][i]; tol--; } else tree[dep+1][R++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l-1] + L-l; } build(l, m, dep+1); build(m+1, r, dep+1);}LL ans;int query(int L, int R, int l, int r, int dep, int k){ if(l == r) return tree[dep][l]; int m = (L+R) >> 1; int cnt = toleft[dep][r]-toleft[dep][l-1]; int ltol = toleft[dep][l-1]-toleft[dep][L-1]; int ltor = l-L-ltol; int mtol = cnt; int mtor = r-l+1-cnt; if(cnt >= k) { if(mtor > 0) { if(ltor > 0) ans += sum[dep+1][mtor+ltor+m]-sum[dep+1][ltor+m]; else ans += sum[dep+1][mtor+m]; } int nextl = L + toleft[dep][l-1]-toleft[dep][L-1]; int nextr = nextl + cnt - 1; return query(L, m, nextl, nextr, dep+1, k); } else { if(mtol > 0) { if(ltol > 0) ans -= sum[dep+1][mtol+ltol+L-1]-sum[dep+1][ltol+L-1]; else ans -= sum[dep+1][mtol+L-1]; } int nextr = r + toleft[dep][R]-toleft[dep][r]; int nextl = nextr-(r-l-cnt); return query(m+1, R, nextl, nextr, dep+1, k-cnt); }}int main(){ int T, cas = 1; scanf("%d", &T);while(T--) { int n; scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d", &tree[0][i]); a[i] = tree[0][i]; } sort(a+1, a+n+1); int q; scanf("%d", &q); build(1, n, 0); printf("Case #%d:\n", cas++); while(q--) { int l, r; scanf("%d %d", &l, &r); l++, r++; ans = 0; int m = (r-l)/2+1; int tmp = query(1, n, l, r, 0, m); if((r-l+1)%2 == 0) ans -= tmp; printf("%I64d\n", ans); } puts(""); }return 0;}
0 0
- hdu 3473 Minimum Sum 划分树
- HDU 3473 Minimum Sum 划分树
- hdu 3473 Minimum Sum(划分树应用)
- hdu 3473 Minimum Sum(划分树)
- HDU 3473 Minimum Sum (划分树)
- HDU 3473 Minimum Sum 划分树
- HDU 3473 Minimum Sum (划分树)
- Minimum Sum - HDU 3473 划分树
- 【划分树】 HDU 3473 Minimum Sum 中位数
- HDU 3473 Minimum Sum (划分树)
- hdu 3473 Minimum Sum(划分树)
- HDU 3473Minimum Sum 划分树
- HDU 3473 Minimum Sum 划分树
- hdu 3473 Minimum Sum(划分树-sum操作)
- HDU 3473 Minimum Sum(划分树)
- hdu 3473 Minimum Sum 划分树的应用
- HDU 3473-Minimum Sum(划分树-求区间sigma最小值)
- HDU-3743 Minimum Sum,划分树模板
- Struts2文件上传
- pta-任务调度合理性
- Struts2文件下载
- HDU 4251 The Famous ICPC Team Again 划分树 区间第K大
- 划分树模版
- HDU 3473 Minimum Sum 划分树
- HDU 3474 Necklace 单调队列
- NetBeans中文界面改英文
- 【腾讯Bugly干货分享】移动App入侵与逆向破解技术-iOS篇
- HDU 4348 To the moon 主席树成段更新
- Java Mail发送邮件各种错误
- big endian
- 在ceph 的admin-node安装calamari详细步骤
- Jboss7启动错误以及添加数据源