【CodeForces】91E Igloo Skyscraper

题意:

n幢摩天大楼,第i幢初始高度为a[i],每个单位时间增长b[i]。

询问区间[x,y]的大楼在t时刻的最大高度。

 

虽然是区间查询,线段树不会搞。

先读入询问,对时间非降排序,离线搞是很显然的。

分成sqrt(n)块,在区间内的每块在常数时间内得到答案,两端暴力答案。

高度y[i]=a[i]+b[i]*t,是直线方程。所以每块在常数时间得到答案,就要维护每块直线的单调性,剔除不影响答案的直线。

由于块内答案是递增的,所以直线的斜率也是递增的。所以对每块的直线斜率非降排序。

设有k1,k2,k3三条直线,且斜率递增,若k1与k2的交点在k3的下方,那么k2显然是多余的。

纸上yy一下,比较时把除法化为乘法,类似求凸包的思想就可以做到的。

总复杂度 O(nsqrt(n))。

  1 #include<cstdio>

  2 #include<cstring>

  3 #include<cmath>

  4 #include<algorithm>

  5 #include<vector>

  6 typedef long long LL;

  7 #define MAXN 100010

  8 #define MAXM 320

  9 #define EPS 1e-8

 10 using namespace std;

 11 int n, block;

 12 struct node {

 13     int pos, high, inc;

 14 };

 15 struct seg {

 16     int pos, x, y, t;

 17 };

 18 node a[MAXN];

 19 seg p[MAXN];

 20 vector<node> b[MAXM];

 21 int pt[MAXM], ans[MAXN];

 22 inline bool cmp1(seg a, seg b) {

 23     return a.t < b.t;

 24 }

 25 inline bool cmp2(node a, node b) {

 26     return a.inc < b.inc;

 27 }

 28 void Init() {

 29     int i;

 30     memset(pt, 0, sizeof(pt));

 31     block = (int) (ceil(sqrt((double) n)) + EPS);

 32     for (i = 0; i < block; i++)

 33         b[i].clear();

 34 }

 35 inline bool Delete(LL a0, LL b0, LL a1, LL b1, LL a2, LL b2) {

 36     return b0 * a1 - a0 * b1 <= a2 * (b0 - b1) + b2 * (a1 - a0);

 37 }

 38 void Increase() {

 39     int i, j, k;

 40     vector<node> tmp;

 41     for (i = 0; i < block; i++) {

 42         tmp.clear();

 43         for (j = 0; j < (int) b[i].size(); j++)

 44             tmp.push_back(b[i][j]);

 45         b[i].clear();

 46         sort(tmp.begin(), tmp.end(), cmp2);

 47         for (j = 0; j < (int) tmp.size(); j++) {

 48             while (b[i].size() > 1) {

 49                 k = (int) b[i].size() - 1;

 50                 if (Delete(b[i][k].high, b[i][k].inc, b[i][k - 1].high,

 51                         b[i][k - 1].inc, tmp[j].high, tmp[j].inc))

 52                     b[i].pop_back();

 53                 else

 54                     break;

 55             }

 56             b[i].push_back(tmp[j]);

 57         }

 58     }

 59 }

 60 int Query(int x, int y, int t) {

 61     LL res, tmp;

 62     int pos, nd, p, q, i;

 63     p = x / block;

 64     q = y / block;

 65     res = 0;

 66     if (p == q) {

 67         for (i = x; i <= y; i++) {

 68             tmp = (LL) a[i].inc * t + a[i].high;

 69             if (tmp > res) {

 70                 res = tmp;

 71                 pos = i;

 72             }

 73         }

 74     } else {

 75         if (x % block) {

 76             for (nd = min(p * block + block, n); x < nd; x++) {

 77                 tmp = (LL) a[x].inc * t + a[x].high;

 78                 if (tmp > res) {

 79                     res = tmp;

 80                     pos = x;

 81                 }

 82             }

 83         }

 84         if (y % block != block - 1) {

 85             for (nd = max(q * block, 1); y >= nd; y--) {

 86                 tmp = (LL) a[y].inc * t + a[y].high;

 87                 if (tmp > res) {

 88                     res = tmp;

 89                     pos = y;

 90                 }

 91             }

 92         }

 93         for (p = x / block; x <= y; x += block, p++) {

 94             while (pt[p] < (int) b[p].size() - 1) {

 95                 if ((LL) b[p][pt[p]].inc * t + b[p][pt[p]].high

 96                         <= (LL) b[p][pt[p] + 1].inc * t + b[p][pt[p] + 1].high)

 97                     pt[p]++;

 98                 else

 99                     break;

100             }

101             tmp = (LL) b[p][pt[p]].inc * t + b[p][pt[p]].high;

102             if (tmp > res) {

103                 res = tmp;

104                 pos = b[p][pt[p]].pos;

105             }

106         }

107     }

108     return pos;

109 }

110 int main() {

111     int i, q;

112     while (~scanf("%d%d", &n, &q)) {

113         Init();

114         for (i = 1; i <= n; i++) {

115             scanf("%d%d", &a[i].high, &a[i].inc);

116             a[i].pos = i;

117             b[i / block].push_back(a[i]);

118         }

119         for (i = 0; i < q; i++) {

120             scanf("%d%d%d", &p[i].x, &p[i].y, &p[i].t);

121             p[i].pos = i;

122         }

123         sort(p, p + q, cmp1);

124         Increase();

125         for (i = 0; i < q; i++)

126             ans[p[i].pos] = Query(p[i].x, p[i].y, p[i].t);

127         for (i = 0; i < q; i++)

128             printf("%d\n", ans[i]);

129     }

130     return 0;

131 }

你可能感兴趣的:(codeforces)