1. 程式人生 > >[bzoj3165] [HEOI2013]Segment

[bzoj3165] [HEOI2013]Segment

每次 class turn 一個 last -o ons 整數 modify

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 

Solution

李超線段樹。

線段樹每個區間記錄一條最優線段。

對於一條線段,以及一條新加的線段,分類討論:

  • 若新線段和舊線段沒有交點,更新之後直接退出就好了。
  • 否則考慮交點和\(mid\)的位置關系,一邊直接覆蓋,另一邊遞歸處理。

對於每次操作,一共會拆成\(O(\log n)\)個區間,每個區間花費\(O(\log n)\)的代價更新,總復雜度\(O(m\log^2n)\)

#include<bits/stdc++.h>
using namespace std;
 
void read(int &x) {
    x=0;int f=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
}
 
void print(int x) {
    if(x<0) putchar('-'),x=-x;
    if(!x) return ;print(x/10),putchar(x%10+48);
}
void write(int x) {if(!x) putchar('0');else print(x);putchar('\n');}

const int maxn = 5e5+10;
const int N = 4e4;

struct data {
    int x,y,xx,yy,id;
    double k,b;    
    double calc(int a) {return k*a+b;}
    void lm(int a) {y=calc(a),x=a;}
    void rm(int a) {yy=calc(a),xx=a;}
};

int judge(data a,data b,int x) {
    if(!a.id) return 1;
    return a.calc(x)==b.calc(x)?a.id>b.id:a.calc(x)<b.calc(x);
}

int cnt;

#define ls p<<1
#define rs p<<1|1
#define mid ((l+r)>>1)

struct Segment_Tree {
    data t[maxn<<2];
    void update(int p,int l,int r,data s) {
        if(s.x<l) s.lm(l);
        if(s.xx>r) s.rm(r);
        if(judge(t[p],s,mid)) swap(s,t[p]);
        if(l==r) return ;
        if(max(s.y,s.yy)<=min(t[p].y,t[p].yy)) return ;
        if(s.k>t[p].k) update(rs,mid+1,r,s);
        else update(ls,l,mid,s);
    }
    void modify(int p,int l,int r,data s) {
        if(s.x<l) s.lm(l);
        if(s.xx>r) s.rm(r);
        if(s.x==l&&s.xx==r) return update(p,l,r,s),void();
        if(s.x<=mid) modify(ls,l,mid,s);
        if(s.xx>mid) modify(rs,mid+1,r,s);
    }
    data query(int p,int l,int r,int x) {
        if(l==r) return t[p];
        data ans=t[p],res;
        if(x<=mid) res=query(ls,l,mid,x);
        else res=query(rs,mid+1,r,x);
        if(judge(ans,res,x)) ans=res;
        return ans;
    }
}SGT;

int main() {
    int t;read(t);
    int lastans=0,id=0;
    data s;
    while(t--) {
        int op,x,y,xx,yy;read(op);
        if(op==1) {
            read(x),read(y),read(xx),read(yy);
            x=(x+lastans-1)%39989+1;
            y=(y+lastans-1)%1000000000+1;
            xx=(xx+lastans-1)%39989+1;
            yy=(yy+lastans-1)%1000000000+1;
            if(x>xx) swap(x,xx),swap(y,yy);
            if(x==xx) {
                y=max(y,yy);
                s=(data){x,y,xx,y,++id,0,1.0*y};
            } else {
                double k=(double)(y-yy)/(1.0*(x-xx));
                s=(data){x,y,xx,yy,++id,k,1.0*y-1.0*x*k};
            }
            SGT.modify(1,1,N,s);
        } else {
            read(x);x=(x+lastans-1)%39989+1;
            write(lastans=SGT.query(1,1,N,x).id);
        }
    }
    return 0;
}

[bzoj3165] [HEOI2013]Segment