【HDOJ】3473 Minimum Sum

划分树解。
主席树解MLE。

  1 /* 3473 */
  2 #include <iostream>
  3 #include <sstream>
  4 #include <string>
  5 #include <map>
  6 #include <queue>
  7 #include <set>
  8 #include <stack>
  9 #include <vector>
 10 #include <deque>
 11 #include <algorithm>
 12 #include <cstdio>
 13 #include <cmath>
 14 #include <ctime>
 15 #include <cstring>
 16 #include <climits>
 17 #include <cctype>
 18 #include <cassert>
 19 #include <functional>
 20 #include <iterator>
 21 #include <iomanip>
 22 using namespace std;
 23 //#pragma comment(linker,"/STACK:102400000,1024000")
 24
 25 #define sti                set<int>
 26 #define stpii            set<pair<int, int> >
 27 #define mpii            map<int,int>
 28 #define vi                vector<int>
 29 #define pii                pair<int,int>
 30 #define vpii            vector<pair<int,int> >
 31 #define rep(i, a, n)     for (int i=a;i<n;++i)
 32 #define per(i, a, n)     for (int i=n-1;i>=a;--i)
 33 #define clr                clear
 34 #define pb                 push_back
 35 #define mp                 make_pair
 36 #define fir                first
 37 #define sec                second
 38 #define all(x)             (x).begin(),(x).end()
 39 #define SZ(x)             ((int)(x).size())
 40 #define lson            l, mid, rt<<1
 41 #define rson            mid+1, r, rt<<1|1
 42 #define LL                __int64
 43
 44 const int maxn = 1e5+5;
 45 int order[maxn];
 46 int val[18][maxn];
 47 int toLeft[18][maxn];
 48 LL sum[18][maxn];
 49 int n;
 50 LL ans;
 51
 52 void Build(int l, int r, int dep) {
 53     if (l == r) {
 54         toLeft[dep][l] = toLeft[dep][l-1] + 1;
 55         sum[dep][l] = sum[dep][l-1] + val[dep][l];
 56         return ;
 57     }
 58
 59     int mid = (l + r) >> 1;
 60     int same = mid - l + 1;
 61     rep(i, l, r+1) {
 62         if (val[dep][i] < order[mid])
 63             --same;
 64     }
 65
 66     int lpos = l, rpos = mid + 1;
 67     rep(i, l, r+1) {
 68         if (val[dep][i] < order[mid]) {
 69             val[dep+1][lpos++] = val[dep][i];
 70         } else if (val[dep][i]==order[mid] && same>0) {
 71             val[dep+1][lpos++] = val[dep][i];
 72             --same;
 73         } else {
 74             val[dep+1][rpos++] = val[dep][i];
 75         }
 76
 77         sum[dep][i] = sum[dep][i-1] + val[dep][i];
 78         toLeft[dep][i] = toLeft[dep][l-1] + lpos - l;
 79     }
 80
 81     Build(l, mid, dep+1);
 82     Build(mid+1, r, dep+1);
 83 }
 84
 85 int Query(int l, int r, int k, int L, int R, int dep) {
 86     if (l == r)
 87         return val[dep][l];
 88
 89     int mid = (L + R) >> 1;
 90     int tmp = toLeft[dep][r] - toLeft[dep][l-1];
 91
 92     if (tmp >= k) {
 93         int s = mid+1+l-L-(toLeft[dep][l-1] - toLeft[dep][L-1]);
 94         int e = mid+r-L+1 - (toLeft[dep][r] - toLeft[dep][L-1]);
 95
 96         ans += sum[dep+1][e] - sum[dep+1][s-1];
 97
 98         int ll = L + toLeft[dep][l-1] - toLeft[dep][L-1];
 99         int rr = ll + tmp - 1;
100
101         return Query(ll, rr, k, L, mid, dep+1);
102     } else {
103         int s = L + toLeft[dep][l-1] - toLeft[dep][L-1];
104         int e = s + tmp - 1;
105
106         ans -= sum[dep+1][e] - sum[dep+1][s-1];
107
108         k -= tmp;
109         int rr = r + toLeft[dep][R] - toLeft[dep][r];
110         int ll = rr - (r-l+1 - tmp) + 1;
111
112         return Query(ll, rr, k, mid+1, R, dep+1);
113     }
114 }
115
116 void solve() {
117     int q;
118
119     sort(order+1, order+1+n);
120     Build(1, n, 0);
121
122     int l, r, kth;
123     int tmp;
124
125     scanf("%d", &q);
126     while (q--) {
127         scanf("%d %d", &l, &r);
128         ++l;
129         ++r;
130         kth = ((l + r) >> 1) - l + 1;
131         ans = 0;
132         tmp = Query(l, r, kth, 1, n, 0);
133         if (((r-l+1) & 1) == 0)
134             ans -= tmp;
135         printf("%I64d\n", ans);
136     }
137 }
138
139 int main() {
140     ios::sync_with_stdio(false);
141     #ifndef ONLINE_JUDGE
142         freopen("data.in", "r", stdin);
143         freopen("data.out", "w", stdout);
144     #endif
145
146     int t;
147
148     scanf("%d", &t);
149     rep(tt, 1, t+1) {
150         scanf("%d", &n);
151         rep(i, 1, n+1) {
152             scanf("%d", &val[0][i]);
153             order[i] = val[0][i];
154         }
155         printf("Case #%d:\n", tt);
156         solve();
157         putchar(‘\n‘);
158     }
159
160     #ifndef ONLINE_JUDGE
161         printf("time = %d.\n", (int)clock());
162     #endif
163
164     return 0;
165 }

数据发生器。

 1 from copy import deepcopy
 2 from random import randint, shuffle
 3 import shutil
 4 import string
 5
 6
 7 def GenDataIn():
 8     with open("data.in", "w") as fout:
 9         t = 10
10         bound = 10**5
11         fout.write("%d\n" % (t))
12         for tt in xrange(t):
13             n = bound
14             q = randint(10, 20)
15             fout.write("%d\n" % (n))
16             L = []
17             for i in xrange(n):
18                 x = randint(1, bound)
19                 L.append(x)
20             fout.write(" ".join(map(str, L)) + "\n")
21             fout.write("%d\n" % (q))
22             for i in xrange(q):
23                 l = randint(0, n-1)
24                 r = randint(l, n-1)
25                 fout.write("%d %d\n" % (l, r))
26
27
28
29 def MovDataIn():
30     desFileName = "F:\eclipse_prj\workspace\hdoj\data.in"
31     shutil.copyfile("data.in", desFileName)
32
33
34 if __name__ == "__main__":
35     GenDataIn()
36     MovDataIn()
时间: 2024-12-23 18:54:12

【HDOJ】3473 Minimum Sum的相关文章

【HDOJ】P2058 The sum problem

题意很简单就是给你一个N和M,让你求在1-N的那些个子序列的值等于M 首先暴力法不解释,简单超时 再仔细想一想可以想到因为1-N是一个等差数列,可以运用我们曾经学过的只是来解决 假设开始的位置为s,结束的位置为t,那么一定要满足这个等式 (s+t)(t-s+1)=2*m 又因为S和T都是整数,所以左边的括号中每一项都是等式 所以s+t和t-s+1一定是2*m的因式 所以分解因式并带入就可以求出s和t 假设 s+t=a t-s+1=b a*b=2*m 解得 s=(a-b+1)/2 t=(a+b-1

【HDOJ】1394 Minimum Inversion Number

逆序数的性质.1. 暴力解 1 #include <stdio.h> 2 3 #define MAXNUM 5005 4 5 int a[MAXNUM]; 6 7 int main() { 8 int n; 9 int i, j, sum, min; 10 11 while (scanf("%d", &n) != EOF) { 12 for (i=0; i<n; ++i) 13 scanf("%d", &a[i]); 14 sum

【HDOJ】1244 Max Sum Plus Plus Plus

这题目一直wa,原来是因为我把JUDGE写错了,对拍了一下午都没检查出来.水DP啊. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 using namespace std; 7 8 #define MAXN 1020 9 #define MAXM 35 10 #define I

【HDOJ】1385 Minimum Transport Cost

Floyd.注意字典序!!! 1 #include <stdio.h> 2 #include <string.h> 3 4 #define MAXNUM 55 5 #define INF 0x1fffffff 6 7 int cost[MAXNUM][MAXNUM]; 8 int path[MAXNUM][MAXNUM]; 9 int taxes[MAXNUM]; 10 int que[MAXNUM]; 11 int n; 12 13 void floyd(int n) { 14

【HDOJ】4704 Sum

数学题.f(n) = 2^(n-1) mod (1e9+7). 1 #include <cstdio> 2 3 #define MAXN 100005 4 5 char buf[MAXN]; 6 __int64 phi = 1e9+6; 7 __int64 mod = 1e9+7; 8 9 __int64 power2(__int64 n) { 10 __int64 ret = 1, base = 2; 11 12 --n; 13 while (n) { 14 if (n & 1) 1

【HDOJ】4956 Poor Hanamichi

基本数学题一道,看错位数,当成大数减做了,而且还把方向看反了.所求为最接近l的值. 1 #include <cstdio> 2 3 int f(__int64 x) { 4 int i, sum; 5 6 i = sum = 0; 7 while (x) { 8 if (i & 1) 9 sum -= x%10; 10 else 11 sum += x%10; 12 ++i; 13 x/=10; 14 } 15 return sum; 16 } 17 18 int main() { 1

【HDOJ】2424 Gary&#39;s Calculator

大数乘法加法,直接java A了. 1 import java.util.Scanner; 2 import java.math.BigInteger; 3 4 public class Main { 5 public static void main(String[] args) { 6 Scanner cin = new Scanner(System.in); 7 int n; 8 int i, j, k, tmp; 9 int top; 10 boolean flag; 11 int t

【HDOJ】2492 Ping pong

线段树+离散化. 1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 5 #define MAXN 20005 6 #define lson l, mid, rt<<1 7 #define rson mid+1, r, rt<<1|1 8 9 int buf[MAXN], bk[MAXN]; 10 int sum[MAXN<<2], n; 11 12 int

【HDOJ】2333 Assemble

二分+贪心策略.其中注释处很重要. 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <cstdlib> 5 #include <algorithm> 6 using namespace std; 7 8 #define MAXL 25 9 #define MAXN 1005 10 #define INF 1000000000 11 12 typed