HDU 3473 Minimum Sum (划分树)
2015-03-31 21:22
531 查看
思路:这道题目可以说,只有你真正理解了划分树之后,你才会想到如何去做.
首先这道题的数学思路是很容易想的.
要使得数学式子的和最大,很明显.这个x是这个区间按从小到大排列之后最中间的数.
所以最后的答案应该是中位数右边的和减去左边的和然后假如这个区间的数的个数为偶数个的话,还需减去一个中位数.
所以这道题除了要记录划分树之外,还用sum[20][MAX]来记录前缀和.
写划分树实在是要细心!!
首先这道题的数学思路是很容易想的.
要使得数学式子的和最大,很明显.这个x是这个区间按从小到大排列之后最中间的数.
所以最后的答案应该是中位数右边的和减去左边的和然后假如这个区间的数的个数为偶数个的话,还需减去一个中位数.
所以这道题除了要记录划分树之外,还用sum[20][MAX]来记录前缀和.
写划分树实在是要细心!!
#define _CRT_SECURE_NO_WARNINGS #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; #define MAX 100050 #define ls rt<<1 #define rs ls|1 #define m (l+r)>>1 int tree[20][MAX]; long long sum[20][MAX]; int sorted[MAX]; int toleft[20][MAX]; long long ans; void build(int l, int r, int dep) { if (l == r) { sum[dep][l] = sum[dep][l - 1] + tree[dep][l]; return; } int mid = m; int cnt = mid - l + 1; for (int i = l; i <= r; i++) { if (tree[dep][i] < sorted[mid]) cnt--; sum[dep][i] = sum[dep][i - 1] + tree[dep][i]; } int lpos = l; int rpos = mid + 1; for (int i = l; i <= r; i++) { if (tree[dep][i] < sorted[mid]) tree[dep + 1][lpos++] = tree[dep][i]; else if (tree[dep][i] == sorted[mid] && cnt) { tree[dep + 1][lpos++] = tree[dep][i]; cnt--; } else tree[dep + 1][rpos++] = tree[dep][i]; toleft[dep][i] = toleft[dep][l - 1] + lpos - l; } build(l, mid, dep + 1); build(mid + 1, r, dep + 1); } int query(int L, int R, int l, int r, int dep, int k) { if (l == r)return tree[dep][l]; int cnt = toleft[dep][R] - toleft[dep][L - 1]; int mid = m; if (cnt >= k) { int ee =R - l + 1 - (toleft[dep][R] - toleft[dep][l - 1]) + mid; int ss =ee-(R-L-cnt); ans += sum[dep + 1][ee] - sum[dep + 1][ss-1]; int newL = l + toleft[dep][L - 1] - toleft[dep][l - 1]; int newR = newL +cnt - 1; return query(newL, newR, l, mid, dep + 1, k); } else { int ss = l + toleft[dep][L - 1] - toleft[dep][l - 1]; int ee = ss + cnt - 1; ans -= sum[dep + 1][ee] - sum[dep + 1][ss-1]; int newR = R + toleft[dep][r] - toleft[dep][R]; int newL = newR - (R - L - cnt); return query(newL, newR, mid + 1, r, dep + 1, k - cnt); } } int main() { int t; scanf("%d", &t); int icase = 1; while (t--) { int n; scanf("%d", &n); ans = 0; memset(tree, 0, sizeof(tree)); memset(sum, 0, sizeof(sum)); for (int i = 1; i <= n; i++) { scanf("%d", &tree[0][i]); sorted[i] = tree[0][i]; } sort(sorted, sorted + n); build(1, n, 0); int a, b, k; scanf("%d", &k); printf("Case #%d:\n", icase++); while (k--) { scanf("%d%d", &a, &b); a++; b++; ans = 0; int temp = query(a, b, 1, n, 0, ((a + b) >> 1) - a + 1); if ((a + b) & 1)ans -= temp; printf("%lld\n", ans); } puts(""); } }
相关文章推荐
- HDU 3473 Minimum Sum 划分树
- HDU 3473-Minimum Sum(划分树-求区间sigma最小值)
- HDU - 3473 Minimum Sum(划分树模板)
- hdu 3473 Minimum Sum(划分树应用)
- HDU 3473 Minimum Sum (划分树)
- HDU 3473 Minimum Sum (划分树)
- HDU 3473 Minimum Sum (划分树)
- HDU 3473 Minimum Sum 划分树,数据结构 难度:1
- 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 再来一波划分树,对划分树累觉不爱。
- HDU 3473 Minimum Sum(划分树,求中位数,小于中位数的和与大于中位数的和)
- HDU 3473 Minimum Sum 划分树
- HDU 3473 Minimum Sum(划分树)
- hdu 3473 Minimum Sum 划分树的应用
- hdu 3473 Minimum Sum