好神奇的线段树呀,第一次接触这种题。
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; }