HEOI2013 Segment

传说中的“李超树”。

大意:给你若干线段,试求横坐标x上的最上方一条线段的编号。无则输出零。

解:用线段树维护。

插入的时候保存自己这个区间上可能成为最大值的线段,被抛弃的则看情况下放。

查询时从最底层向上查一路,沿途取得答案。

函数我用的是斜截式来存,脑残的把b写错了.....getY还传错参了。

调掉之后就一发AC!哈哈哈

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cmath>
  4 const int N = 40005, M = 100010, INF = 0x3f3f3f3f;
  5 const double eps = 1e-10;
  6 
  7 struct SG {
  8     double k, b;
  9     int l, r;
 10 }sg[M];
 11 
 12 inline double getY(int a, int x) {
 13     SG t = sg[a];
 14     if(x < t.l || t.r < x || !a) {
 15         return (double)(-INF);
 16     }
 17     if(fabs(t.k - INF) < eps) {
 18         return t.b;
 19     }
 20     return t.k * x + t.b;
 21 }
 22 
 23 struct SegmentTree {
 24     int ans[N << 2];
 25 
 26     void add(int L, int R, int v, int l, int r, int o) {
 27         //printf("add : %d %d %d %d %d \n", L, R, v, l, r);
 28         int mid = (l + r) >> 1;
 29         if(L <= l && r <= R) {
 30             if(!ans[o]) { /// no segment
 31                 ans[o] = v;
 32                 //printf("ans[] = %d \n", ans[o]);
 33                 return;
 34             }
 35             if(l == r) { /// only one
 36                 if(getY(v, r) > getY(ans[o], r)) {
 37                     ans[o] = v;
 38                     //printf("ans[] = %d \n", ans[o]);
 39                 }
 40                 return;
 41             }
 42             double A = getY(v, l), B = getY(v, mid), C = getY(v, r);
 43             double D = getY(ans[o], l), E = getY(ans[o], mid), F = getY(ans[o], r);
 44             if(A > D && C > F) {
 45                 ans[o] = v;
 46                 //printf("ans[] = %d \n", ans[o]);
 47                 return;
 48             }
 49             /*if(v == 3 && l == 4 && r == 5) {
 50                 printf("B = %lf  E = %lf\n", B, D);
 51             }*/
 52             if(!(A > D) && !(C > F)) {
 53                 return;
 54             }
 55             if(B > E) {
 56                 if(sg[v].k > sg[ans[o]].k) {
 57                     add(l, mid, ans[o], l, mid, o << 1);
 58                     ans[o] = v;
 59                     //printf("ans[] = %d \n", ans[o]);
 60                 }
 61                 else {
 62                     add(mid + 1, r, ans[o], mid + 1, r, o << 1 | 1);
 63                     ans[o] = v;
 64                     //printf("ans[] = %d \n", ans[o]);
 65                 }
 66             }
 67             else {
 68                 if(sg[v].k > sg[ans[o]].k) {
 69                     add(mid + 1, r, v, mid + 1, r, o << 1 | 1);
 70                 }
 71                 else {
 72                     add(l, mid, v, l, mid, o << 1);
 73                 }
 74             }
 75             return;
 76         }
 77         if(L <= mid) {
 78             add(L, R, v, l, mid, o << 1);
 79         }
 80         if(mid < R) {
 81             add(L, R, v, mid + 1, r, o << 1 | 1);
 82         }
 83         return;
 84     }
 85     int ask(int p, int l, int r, int o) {
 86         if(l == r) {
 87             //printf("ask: %d %d %d return %d \n", p, l, r, ans[o]);
 88             return ans[o];
 89         }
 90         int mid = (l + r) >> 1;
 91         int A;
 92         if(p <= mid) {
 93             A = ask(p, l, mid, o << 1);
 94         }
 95         else {
 96             A = ask(p, mid + 1, r, o << 1 | 1);
 97         }
 98         int t = ans[o];
 99         if(getY(A, p) - eps > getY(t, p)) {
100             t = A;
101         }
102         else if(fabs(getY(A, p) - getY(t, p)) < eps) {
103             t = std::min(t, A);
104         }
105         //printf("ask: %d %d %d return %d \n", p, l, r, t);
106         return t;
107     }
108 }SgT;
109 
110 int main() {
111     int n, MO = 39989, lastans = 0, num = 0;
112     scanf("%d", &n);
113     for(int i = 1, f, x, xx, y, yy; i <= n; i++) {
114         scanf("%d", &f);
115         if(f) {
116             scanf("%d%d%d%d", &x, &y, &xx, &yy);
117             x = (x + lastans - 1) % MO + 1;
118             xx = (xx + lastans - 1) % MO + 1;
119             y = (y + lastans - 1) % 1000000000 + 1;
120             yy = (yy + lastans - 1) % 1000000000 + 1;
121             if(x > xx) {
122                 std::swap(x, xx);
123                 std::swap(y, yy);
124             }
125             sg[++num].l = x;
126             sg[num].r = xx;
127             if(x == xx) {
128                 sg[num].k = 1.0 * INF;
129                 sg[num].b = 1.0 * std::max(y, yy);
130             }
131             else {
132                 sg[num].k = 1.0 * (y - yy) / (x - xx);
133                 sg[num].b = y - sg[num].k * x;
134             }
135             SgT.add(x, xx, num, 1, MO, 1);
136             /*for(int i = 1; i <= 11; i++) {
137                 SgT.ask(i, 1, MO, 1);
138             }
139             puts("");*/
140         }
141         else {
142             scanf("%d", &x);
143             x = (x + lastans - 1) % MO + 1;
144             lastans = SgT.ask(x, 1, MO, 1);
145             printf("%d\n", lastans);
146         }
147     }
148 
149     /*puts("");
150     for(int i = 1; i <= num; i++) {
151         printf("%lf %lf %d %d \n", sg[i].k, sg[i].b, sg[i].l, sg[i].r);
152     }*/
153 
154     return 0;
155 }
AC代码

调起来真难...很不理解为什么有人的李超树代码只有我的 1 / 3 长

 

posted @ 2018-07-23 17:24  garage  阅读(100)  评论(0编辑  收藏  举报