题意:

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 }
posted on 2012-08-28 18:18  DrunBee  阅读(502)  评论(0编辑  收藏  举报