bzoj3165 [Heoi2013]Segment(李超线段树)

李超线段树维护线段!
找到覆盖的logn个区间,然后像直线一样去做就好了。
复杂度 O(nlog2n)
注意特殊处理不存在斜率的线段。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
#define ll long long
#define inf 0x3f3f3f3f
#define N 100010
#define mod 39989
#define mod1 1000000000
#define eps 1e-8
inline char gc(){
    static char buf[1<<16],*S,*T;
    if(S==T){T=(S=buf)+fread(buf,1,1<<16,stdin);if(T==S) return EOF;}
    return *S++;
}
inline int read(){
    int x=0,f=1;char ch=gc();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
    while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=gc();
    return x*f;
}
int n=40000,ans=0,m=0,c[40000];
inline int re(int x){return (x+ans-1)%mod+1;}
inline int re1(int x){return (x+ans-1)%mod1+1;}
struct Line{
    int l,r;double k,b;
    double f(int x){return k*x+b;}
}a[N];
struct node{
    int x;
}tr[160010];
inline int sgn(double x){return (x>-eps)-(x<eps);}
inline int Max(int x,int y,int v){
    if(!x) return y;
    int ff=sgn(a[x].f(v)-a[y].f(v));
    if(ff==1||ff==0&&x<y) return x;return y;
}
inline void ins(int p,int l,int r,int x,int y,int id){
    if(x<=l&&r<=y){
        if(!tr[p].x){tr[p].x=id;return;}
        int fl=sgn(a[tr[p].x].f(l)-a[id].f(l)),fr=sgn(a[tr[p].x].f(r)-a[id].f(r));
        if(fl>=0&&fr>=0) return;
        if(fl==-1&&fr==-1){tr[p].x=id;return;}int mid=l+r>>1;
        if(fl!=-1){
            if(a[tr[p].x].f(mid)>a[id].f(mid)) ins(p<<1|1,mid+1,r,x,y,id);
            else ins(p<<1,l,mid,x,y,tr[p].x),tr[p].x=id; 
        }else{
            if(a[tr[p].x].f(mid)>a[id].f(mid)) ins(p<<1,l,mid,x,y,id);
            else ins(p<<1|1,mid+1,r,x,y,tr[p].x),tr[p].x=id;
        }return;
    }int mid=l+r>>1;
    if(x<=mid) ins(p<<1,l,mid,x,y,id);
    if(y>mid) ins(p<<1|1,mid+1,r,x,y,id);
}
inline int ask(int p,int l,int r,int x){
    if(l==r) return tr[p].x;
    int mid=l+r>>1;
    if(x<=mid) return Max(tr[p].x,ask(p<<1,l,mid,x),x);
    return Max(tr[p].x,ask(p<<1|1,mid+1,r,x),x);
}
int main(){
//  freopen("a.in","r",stdin);
    int owo=read();
    while(owo--){
        int op=read();
        if(op){
            int x0=re(read()),y0=re1(read()),x1=re(read()),y1=re1(read());
            a[++m].l=min(x0,x1);a[m].r=max(x0,x1);
            if(x0==x1){a[m].k=0;a[m].b=max(y0,y1);c[x0]=Max(c[x0],m,x0);continue;}
            a[m].k=(y1-y0)*1.0/(x1-x0),a[m].b=y0-a[m].k*x0;
            ins(1,1,n,a[m].l,a[m].r,m);
        }else{
            int x=re(read());ans=ask(1,1,n,x);
            ans=Max(c[x],ans,x);printf("%d\n",ans);
        }
    }return 0;
}

猜你喜欢

转载自blog.csdn.net/icefox_zhx/article/details/80176752