好神奇的线段树呀,第一次接触这种题。
http://www.cnblogs.com/idy002/p/4315959.html
对x坐标建一棵线段树,每个节点记录一下覆盖这个区间的是哪条线段。
插入一条线段,
如果线段没有覆盖当前的区间,那么递归它的儿子。
如果线段覆盖了当前的区间,
如果当前区间没有被线段覆盖,那么就直接更新。
如果当前区间被线段覆盖了,如果两个线段没有交点,那么取高的那一个,否则取长的那个,那么拿短的线段去更新儿子。
查询:
从根节点开始一直查询到底,中间每一条线段都要计算。
因为线段会被拆成O(log n)个区间,每个区间又要向下延伸O(log n)步,所以复杂度是O(n log^2 n)的。
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<algorithm>
#include<iostream>
#define maxn 100010
#define mod 39989
#define mody 1000000000
#define eps 1e-10
using namespace std;
struct yts
{
int l,r;
int flag;
}t[4*maxn];
struct line
{
int l,r;
double k,b;
double f(int x)
{
return k*x+b;
}
}st[maxn];
int wi[maxn];
double wy[maxn];
int n,m,tot,ans,ansi,T;
double ansy;
line calc(int x2,int y2,int x3,int y3)
{
line ans;
ans.l=min(x2,x3);ans.r=max(x2,x3);
if (x2!=x3) ans.k=(y2-y3)/(double)(x2-x3),ans.b=y2-x2*ans.k;
else ans.k=0.0,ans.b=max(y2,y3);
return ans;
}
int cross(int i,int j)
{
return floor((st[i].b-st[j].b)/(st[j].k-st[i].k));
}
int sg(double x)
{
return (x>-eps)-(x<eps);
}
void update(int i,int x)
{
double y=st[x].f(i);
bool s=sg(y-wy[i]);
if (!wi[i] || (s>0 || (s==0 && x<wi[i])))
{
wy[i]=y;wi[i]=x;
}
}
void build(int i,int l,int r)
{
t[i].l=l;t[i].r=r;t[i].flag=0;
if (l==r) return;
int mid=(l+r)/2;
build(i*2,l,mid);build(i*2+1,mid+1,r);
}
void modify(int i,int x)
{
if (st[x].l<=t[i].l && t[i].r<=st[x].r)
{
if (!t[i].flag)
{
t[i].flag=x;
return;
}
int mid=(t[i].l+t[i].r)/2;
bool lu=sg((st[x].f(t[i].l)-st[t[i].flag].f(t[i].l)))>0;
bool ru=sg((st[x].f(t[i].r)-st[t[i].flag].f(t[i].r)))>0;
if (lu && ru) t[i].flag=x;
else
if (lu || ru)
{
int tt=cross(x,t[i].flag);
if (tt<=mid && lu) modify(i*2,x);
if (tt<=mid && ru) modify(i*2,t[i].flag),t[i].flag=x;
if (tt>mid && ru) modify(i*2+1,x);
if (tt>mid && lu) modify(i*2+1,t[i].flag),t[i].flag=x;
}
else update(t[i].l,x),update(t[i].r,x);
return;
}
int mid=(t[i].l+t[i].r)/2;
if (st[x].l<=mid) modify(i*2,x);
if (mid<st[x].r) modify(i*2+1,x);
}
void query(int i,int x)
{
if (t[i].flag)
{
double y=st[t[i].flag].f(x);
int s=sg(y-ansy);
if (s>0 || (s==0 && t[i].flag<ansi))
{
ansy=y;ansi=t[i].flag;
}
}
if (t[i].l==t[i].r) return;
int mid=(t[i].l+t[i].r)/2;
if (x<=mid) query(i*2,x);
if (mid<x) query(i*2+1,x);
}
int main()
{
scanf("%d",&T);
build(1,1,mod);
while (T--)
{
int op,x2,y2,x3,y3;
scanf("%d",&op);
if (op)
{
scanf("%d%d%d%d",&x2,&y2,&x3,&y3);
x2=(x2+ans-1)%mod+1;y2=(y2+ans-1)%mody+1;
x3=(x3+ans-1)%mod+1;y3=(y3+ans-1)%mody+1;
st[++tot]=calc(x2,y2,x3,y3);
modify(1,tot);
}
else
{
scanf("%d",&x2);
x2=(x2+ans-1)%mod+1;
ansi=0;ansy=-1.0;
query(1,x2);
int s=sg(wy[x2]-ansy);
if (s>0 || (s==0 && wi[x2]<ansi)) ansi=wi[x2];
ans=ansi;
printf("%d\n",ans);
}
}
return 0;
}