BZOJ 3165: [Heoi2013]Segment

3165: [Heoi2013]Segment

Time Limit: 40 Sec  Memory Limit: 256 MB
Submit: 465  Solved: 187
[Submit][Status][Discuss]

Description

要求在平面直角坐标系下维护两个操作: 
1.在平面上加入一条线段。记第i条被插入的线段的标号为i。 
2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号。  

Input

 
第一行一个整数n,表示共n 个操作。 
接下来n行,每行第一个数为0或1。 
 
若该数为 0,则后面跟着一个正整数 k,表示询问与直线  
x = ((k +lastans–1)%39989+1)相交的线段中交点(包括在端点相交的情形)最靠上的线段的编号,其中%表示取余。若某条线段为直线的一部分,则视作直线与线段交于该线段y坐标最大处。若有多条线段符合要求,输出编号最小的线段的编号。 
若该数为 1,则后面跟着四个正整数 x0, y0, x 1, y 1,表示插入一条两个端点为 
((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和((x
1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的线段。 
其中lastans为上一次询问的答案。初始时lastans=0。 
 
 

Output

对于每个 0操作,输出一行,包含一个正整数,表示交点最靠上的线段的编号。若不存在与直线相交的线段,答案为0。 

Sample Input

6
1 8 5 10 8
1 6 7 2 6
0 2
0 9
1 4 7 6 7
0 5

Sample Output

2
0 3

HINT

 

对于100%的数据,1 ≤ n ≤ 10^5 , 1 ≤  k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9。

 

Source

 
[Submit][Status][Discuss]


HOME Back

 

线段树维护线段,23333

 

  1 #include <bits/stdc++.h>
  2 
  3 struct line
  4 {
  5     int lt, rt;
  6     double k, b;
  7     
  8     line(void) {};
  9     
 10     line(int x0, int y0, int x1, int y1)
 11     {
 12         if (x0 < x1)
 13             lt = x0, rt = x1;
 14         else
 15             lt = x1, rt = x0;
 16         
 17         if (x0 == x1)
 18         {
 19             k = 0.0;
 20             b = y0 > y1 ? y0 : y1;
 21         }
 22         else
 23         {
 24             k = 1.0 * (y0 - y1) / (x0 - x1);
 25             b = y0 - x0 * k;
 26         }
 27     }
 28     
 29     inline double f(int x)
 30     {
 31         return k * x + b;
 32     }
 33 }ln[100005]; int tot;
 34 
 35 int sg(double x)
 36 {
 37     static const double eps = 1e-10;
 38     
 39     return (x > -eps) - (x < +eps);
 40 }
 41 
 42 int cross(int i, int j)
 43 {
 44     return floor((ln[i].b - ln[j].b) / (ln[j].k - ln[i].k));
 45 }
 46 
 47 int flg[160005];
 48 
 49 int wi[40005]; double wy[40005];
 50 
 51 inline void update(int x, int p)
 52 {
 53     double y = ln[p].f(x);
 54     
 55     int s = sg(y - wy[x]);
 56     
 57     if (!wi[x] || s > 0 || (!s && p < wi[x]))
 58         wi[x] = p, wy[x] = y;
 59 }
 60 
 61 void insert(int t, int l, int r, int p)
 62 {
 63     if (ln[p].lt <= l && ln[p].rt >= r)
 64     {
 65         if (!flg[t])flg[t] = p;
 66         else
 67         {
 68             int mid = (l + r) >> 1;
 69             
 70             bool lu = sg(ln[p].f(l) - ln[flg[t]].f(l)) > 0;
 71             bool ru = sg(ln[p].f(r) - ln[flg[t]].f(r)) > 0;
 72             
 73             if (lu && ru)flg[t] = p;
 74             else if (lu || ru)
 75             {
 76                 int tt = cross(p, flg[t]);
 77                 if (tt <= mid)
 78                 {
 79                     if (lu)
 80                         insert(t << 1, l, mid, p);
 81                     else
 82                         insert(t << 1, l, mid, flg[t]), flg[t] = p;
 83                 }
 84                 else
 85                 {
 86                     if (ru)
 87                         insert(t << 1 | 1, mid + 1, r, p);
 88                     else
 89                         insert(t << 1 | 1, mid + 1, r, flg[t]), flg[t] = p;
 90                 }
 91             }
 92             else
 93             {
 94                 update(l, p);
 95                 update(r, p);
 96             }
 97         }
 98     }
 99     else
100     {
101         int mid = (l + r) >> 1;
102         
103         if (ln[p].lt <= mid)
104             insert(t << 1, l, mid, p);
105         if (ln[p].rt > mid)
106             insert(t << 1 | 1, mid + 1, r, p);
107     }
108 }
109 
110 int ansi; double ansy;
111 
112 void query(int t, int l, int r, int x)
113 {
114     if (flg[t])
115     {
116         double y = ln[flg[t]].f(x);
117         
118         int s = sg(y - ansy);
119         
120         if (s > 0 || (!s && flg[t] < ansi))
121             ansi = flg[t], ansy = y;
122     }
123     
124     if (l != r)
125     {
126         int mid = (l + r) >> 1;
127         
128         if (x <= mid)
129             query(t << 1, l, mid, x);
130         if (x > mid)
131             query(t << 1 | 1, mid + 1, r, x);
132     }
133 }
134 
135 signed main(void)
136 {
137     int n; scanf("%d", &n);
138     
139     for (int ans = 0; n--; )
140     {
141         int op; scanf("%d", &op);
142         
143         if (op)    // insert segment
144         {
145             int x0, y0, x1, y1;
146             
147             scanf("%d%d%d%d", &x0, &y0, &x1, &y1);
148             
149             x0 = (x0 + ans - 1) % 39989 + 1;
150             x1 = (x1 + ans - 1) % 39989 + 1;
151             y0 = (y0 + ans - 1) % 1000000000 + 1;
152             y1 = (y1 + ans - 1) % 1000000000 + 1;
153             
154             ln[++tot] = line(x0, y0, x1, y1);
155             
156             insert(1, 1, 40000, tot);
157         }
158         else    // query segment
159         {
160             int x; scanf("%d", &x);
161             
162             x = (x + ans - 1) % 39989 + 1;
163             
164             ansi = wi[x], ansy = wy[x];
165             
166             query(1, 1, 40000, x);
167             
168             printf("%d\n", ans = ansi);
169         }
170     }
171 }

 

@Author: YouSiki

 

posted @ 2017-01-17 16:01  YouSiki  阅读(330)  评论(0编辑  收藏  举报