[hdoj5192] 树状数组

枚举所有的区间。对于确定的区间,假设最终的高度为h,

代价是max((Hih),(hHj))Hih,Hjh) 等价于max(Hicnt(i)h,cnt(j)hHj) (cnt(i)表示满足Hih的堆数, cnt(j)表示满足Hjh 的堆数)。Hicnt(i)h关于h呈递减,cnt(j)hHj关于h呈递增。一个递减到0,一个从0开始递增,所以代价与h的函数图像是V字形的,交点处代价最小。此时 Hicnt(i)h=cnt(j)hHjh=Hi+Hjcnt(i)+cnt(j),分母是总堆数W,分子是这个区间积木的总个数。h实际上就是这个区间的平均高度aver。考虑到四舍五入,答案是aver或者aver+1,当然还需要与题目给定的H做下比较,最终的方案是这3个数之一。确定高度之后,把高的变矮需要知道比当前高度大的个数以及高度总和,把矮的变高类似。因此添加一堆和删除一堆时,需要维护个数和总和。可以通过树状数组维护,整个问题的复杂度O((n+W)logn).
代码如下:
  1 #include <iostream>

  2 #include <cstdio>

  3 #include <algorithm>

  4 #include <cstring>

  5 #include <map>

  6 #include <queue>

  7 #include <cmath>

  8 #include <vector>

  9 #include <ctime>

 10 #include <cctype>

 11 

 12 using namespace std;

 13 

 14 #define mem0(a) memset(a, 0, sizeof(a))

 15 #define lson l, m, rt << 1

 16 #define rson m + 1, r, rt << 1 | 1

 17 #define define_m int m = (l + r) >> 1

 18 #define Rep(a, b) for(int a = 0; a < b; a++)

 19 #define lowbit(x) ((x) & (-(x)))

 20 #define constructInt3(name, a, b, c) name(int a = 0, int b = 0, int c = 0): a(a), b(b), c(c) {}

 21 #define constructInt2(name, a, b) name(int a = 0, int b = 0): a(a), b(b) {}

 22 

 23 typedef double db;

 24 typedef long long LL;

 25 

 26 const int dx[4] = {1, 0, -1, 0};

 27 const int dy[4] = {0, -1, 0, 1};

 28 const int maxn = 1e4 + 7;

 29 const int maxm = 1e5 + 7;

 30 const int MD = 1e9 +7;

 31 

 32 struct Point {

 33     int x, y;

 34     bool operator < (const Point &opt) const {

 35         return x < opt.x || x == opt.x && y < opt.y;

 36     }

 37     Point operator - (const Point &opt) const {

 38         return Point(x - opt.x, y - opt.y);

 39     }

 40     constructInt2(Point, x, y);

 41     void inp() {

 42         scanf("%d %d", &x, &y);

 43     }

 44     void outp() {

 45         printf("(%d, %d), ", x, y);

 46     }

 47 };

 48 

 49 struct Trie {

 50         const static int char_size = 26;

 51         int cc;

 52         int cht[100010][char_size];

 53         int mark[100010];

 54         Trie() { cc = 0; mem0(mark); mem0(cht); }

 55         int Idex(char ch) { return ch - '0'; }

 56         void Insert(char s[], int v) {

 57                 int pos = 0;

 58                 for(int i = 0; s[i]; i++) {

 59                         int id = Idex(s[i]);

 60                         if(!cht[pos][id]) cht[pos][id] = ++cc;

 61                         pos = cht[pos][id];

 62                 }

 63                 mark[pos] = v;

 64         }

 65         bool Find(char s[]) {

 66                 int pos = 0;

 67                 for(int i = 0; s[i]; i++) {

 68                         int id = Idex(s[i]);

 69                         if(!cht[pos][id]) return 0;

 70                         pos = cht[pos][id];

 71                 }

 72                 return mark[pos];

 73         }

 74 };

 75 

 76 struct KMP {

 77         int next[1000010];

 78         void GetNext(char s[]) {

 79                 mem0(next);

 80                 next[0] = next[1] = 0;

 81                 for(int i = 1; s[i]; i++) {

 82                         int j = next[i];

 83                         while(j && s[i] != s[j]) j = next[j];

 84                         next[i + 1] = s[j] == s[i]? j + 1 : 0;

 85                 }

 86         }

 87         void Match(char s[], char t[]) {

 88                 int j = 0, len = strlen(t);

 89                 for(int i = 0; s[i]; i++) {

 90                         while(j && s[i] != t[j]) j = next[j];

 91                         if(s[i] == t[j]) j++;

 92                         if(j == len) printf("%d\n", i - len + 1);

 93                 }

 94         }

 95 };

 96 

 97 struct Matrix {

 98         int a[3][3];

 99         Matrix operator * (const Matrix &_A) const {

100                 Matrix tmp;

101                 mem0(tmp.a);

102                 for(int i = 0; i < 3; i++) {

103                         for(int j = 0; j < 3; j++) {

104                                 for(int k = 0; k < 3; k++) {

105                                         tmp.a[i][j] = ((LL)a[i][k] * _A.a[k][j] + tmp.a[i][j]) % MD;

106                                 }

107                         }

108                 }

109                 return tmp;

110         }

111 };

112 

113 struct Edge {

114     int u, v;

115     constructInt2(Edge, u, v);

116 };

117 

118 struct Segment {

119         Point a, b;

120         void inp() {

121                 scanf("%d%d%d%d", &a.x, &a.y, &b.x, &b.y);

122                 if(a.x > b.x) {

123                         swap(a.x, b.x);

124                         swap(a.y, b.y);

125                 }

126         }

127 };

128 

129 Matrix CalcMatrix(Matrix a, int n) {

130         if(n == 1) return a;

131         Matrix tmp = CalcMatrix(a, n >> 1);

132         tmp = tmp * tmp;

133         if(n & 1) tmp = tmp * a;

134         return tmp;

135 }

136 

137 inline int ReadInt() {

138     char c = getchar();

139     while(!isdigit(c)) c = getchar();

140 

141     int x = 0;

142     while(isdigit(c)) {

143         x = x * 10 + c - '0';

144         c = getchar();

145     }

146     return x;

147 }

148 

149 inline void WriteInt(int i) {

150     int p = 0;

151     static int buf[10];

152     if(i == 0) p++;

153     else while(i) {

154         buf[p++] = i % 10;

155         i /= 10;

156     }

157     for(int j = p - 1; j; j--) putchar('0' + buf[j]);

158 }

159 

160 int Cross(Point a, Point b) {

161     return a.x * b.y - a.y * b.x;

162 }

163 

164 int Dist2(Point a, Point b) {

165     int x = a.x - b.x, y = a.y - b.y;

166     return x * x + y * y;

167 }

168 int ConvexHull(Point *p, int n, Point *ch) {

169     sort(p, p + n);

170     int m = 0;

171     for (int i = 0; i < n; i++) {

172         while (m > 1 && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m--;

173         ch[m++] = p[i];

174     }

175     int k = m;

176     for (int i = n - 2; i >= 0; i--) {

177         while (m > k && Cross(ch[m - 1] - ch[m - 2], p[i] - ch[m - 2]) <= 0) m--;

178         ch[m++] = p[i];

179     }

180     if (n > 1) m--;

181     return m;

182 }

183 

184 template<class edge> struct Graph {

185     vector<vector<edge> > adj;

186     Graph(int n) { adj.clear(); adj.resize(n + 5); }

187     Graph() { adj.clear(); }

188     void resize(int n) { adj.resize(n + 5); }

189     void add(int s, edge e){ adj[s].push_back(e); }

190     void del(int s, edge e) { adj[s].erase(find(iter(adj[s]), e)); }

191     void clear() { adj.clear(); }

192     vector<edge>& operator [](int t) { return adj[t]; }

193 };

194 

195 template<class T> struct TreeArray {

196     vector<T> c;

197     int maxn;

198     TreeArray(int n) { c.resize(n + 5); maxn = n; }

199     TreeArray() { c.clear(); maxn = 0; }

200     void clear() { memset(&c[0], 0, sizeof(T) * maxn); }

201     void resize(int n) { c.resize(n + 5); maxn = n; }

202     void add(int p, T x) { while (p < maxn) { c[p] += x; p += lowbit(p); } }

203     T get(int p) { T res = 0; while (p) { res += c[p]; p -= lowbit(p); } return res; }

204     T range(int a, int b) { return get(b) - get(a - 1); }

205 };

206 

207 int n, W, H, a[160000];

208 LL sum[160000], step, maxh;

209 TreeArray<LL> ta(50001), ta0(50001);

210 void Check(int h, int r) {

211     if (sum[n + 2 * W - 1] < (LL)h * W) return ;

212     LL sum1 = ta0.get(h + 1), sumall = sum[r] - sum[r - W], c = ta.get(h + 1);

213     LL newsum1 = h * c - sum1, newsum2 = sumall - h * W + newsum1;

214     LL res = max(newsum1, newsum2);

215     if (res < step || res == step && h > maxh) {

216         step = res;

217         maxh = h;

218     }

219 }

220 int main() {

221     //freopen("in.txt", "r", stdin);

222     while (cin >> n >> W >> H) {

223         mem0(a);

224         for (int i = 0; i < n; i++) {

225             scanf("%d", a + i + W);

226         }

227         int total = n + 2 * W;

228         for (int i = 1; i < total; i++) sum[i] = sum[i - 1] + a[i];

229 

230         if (sum[total - 1] < (LL)H * W) {

231             puts("-1");

232             continue;

233         }

234 

235         ta.clear();

236         ta0.clear();

237         step = H * W;

238         maxh = H;

239         ta.add(1, W );

240         ta0.add(1, 0);

241 

242         for (int i = W; i < total; i++) {

243             int num = sum[i] - sum[i - W], ave = num / W;

244             if (ave < H) ave = H;

245             ta.add(a[i - W] + 1, -1);

246             ta0.add(a[i - W] + 1, -a[i - W]);

247             ta.add(a[i] + 1, 1);

248             ta0.add(a[i] + 1, a[i]);

249             Check(ave, i);

250             Check(ave + 1, i);

251         }

252         cout << maxh << " " << step << endl;

253     }

254     return 0;

255 }
View Code

 

你可能感兴趣的:(树状数组)