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

时间: 2024-08-08 02:00:18

BZOJ 3165: [Heoi2013]Segment的相关文章

Bzoj 3165 [Heoi2013]Segment题解

3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 668  Solved: 276[Submit][Status][Discuss] Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i. 2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. Input 第一行一个整数n,表示共n 个操作. 接下来n行,每行第一

bzoj 3165: [Heoi2013]Segment 动态凸壳

3165: [Heoi2013]Segment Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 202  Solved: 89[Submit][Status] Description 要求在平面直角坐标系下维护两个操作: 1.在平面上加入一条线段.记第i条被插入的线段的标号为i.   2.给定一个数k,询问与直线 x = k相交的线段中,交点最靠上的线段的编号. Input 第一行一个整数n,表示共n 个操作. 接下来n行,每行第一个数为0或1.

BZOJ 3165 Segment

同上题. #include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define maxn 40000 using namespace std; long long n,m,type,a,b,c,d,root,tot=0,ls[maxn<<2],rs[maxn<<2],cnt=0; bool flag[maxn<<2]; long

BZOJ 3166: [Heoi2013]Alo

3166: [Heoi2013]Alo Time Limit: 20 Sec  Memory Limit: 256 MBSubmit: 923  Solved: 437[Submit][Status][Discuss] Description Welcome to ALO ( Arithmetic and Logistic Online).这是一个VR MMORPG ,如名字所见,到处充满了数学的谜题.现在你拥有n颗宝石,每颗宝石有一个能量密度,记为ai,这些宝石的能量密度两两不同.现在你可以选

BZOJ3165 [Heoi2013]Segment

恩..线段树维护凸壳...什么鬼 介绍什么的略.为甚我的程序略长... 1 /************************************************************** 2 Problem: 3165 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:1820 ms 7 Memory:5180 kb 8 ************************************************

bzoj 3165

题意: 给出平面上一些线段,在线询问与x=x0相交的线段中,交点y最大的线段的标号,支持添加线段. 大概思路: 用线段树维护,线段树每个线段记录贯穿(左右端点在该区间外或上)的原线段中能覆盖其它贯穿该线段的原线段(即每个线段树线段记录贯穿该线段的所有原线段中“最高”的) 细节: 添加原线段s到线段树线段nd: 如果s不能覆盖,根据s的大小传递到左儿子或右儿子或都传 如果s覆盖, 如果原本没有线段,则直接设置为s 如果有线段ss,求s与ss的交点,将短(比较x上投影的长度)的线段“压”到交点所在儿

P4097 [HEOI2013]Segment(李超树)

链接 https://www.luogu.org/problemnew/show/P4097 https://www.lydsy.com/JudgeOnline/problem.php?id=3165 思路 还是模板超哥线段树 注意没有斜率的时候 还有貌似卡精度了,long doule不行,需要eps判等(也许是我太丑了) 确实拍出许多毛病,但是懒得提交直接下数据 下错了,对拍了两小时没看出啥毛病,最后测了测std才发现,真的是zz 代码 #include <iostream> #includ

BZOJ 3167: [Heoi2013]Sao

Description 一个排列,满足一些限制,形成一个树形结构,求方案数\(T\leqslant 5,n\leqslant 1\times 10^3\) Solution 树形DP. \(f[i][j]\)表示\(i\)是在他的子树中排名为\(j\). 也是暴力合并信息,复杂度分析同上题. Code /************************************************************** Problem: 3167 User: BeiYu Language

BZOJ 3168 Heoi2013 钙铁锌硒维生素 矩阵求逆+匈牙利算法

题目大意:给定一个n?n的满秩矩阵A和一个n?n的矩阵B.求一个字典序最小的1...n的排列a满足将随意一个Ai换成Bai后矩阵A仍然满秩 我们考虑建立一个二分图.假设Ai能换成Bj.就在i?>j之间连接一条边 那么这个图怎么建呢? 考虑一个行向量Bi,我们在A中找到最小的行向量集合满足Bi能够被这些行向量线性表出,那么显然Bi仅仅能替换这些行向量 我们能够设矩阵C满足C?A=B,那么C=B?A?1 Ci,j≠0表示Bi的线性表出须要Aj,因此CT就是这个二分图的邻接矩阵 如今我们有了一个二分图