BZOJ3165: [Heoi2013]Segmentphp
並不知道爲何在$BZOJ$上,這是道權限題。。。html
本蒟蒻表示沒錢氪金。。。ios
這裏附上洛谷的題面:post
要求在平面直角座標系下維護兩個操做:url
輸入格式:spa
第一行一個整數 n,表示共 n 個操做htm
接下來 n 行,每行第一個數爲 0 或 1blog
若該數爲 0,則後面跟着一個正整數 k,表示詢問與直線 x = ((k + lastans – 1)%39989+1)相交的線段中交點(包括在端點相交的情形)最靠上的線段的編號,其中%表示取餘。若某條線段爲直線的一部分,則視做直線與線段交於該線段 y 座標最大處。如有多條線段符合要求,輸出編號最小的線段的編號get
若該數爲 1,則後面跟着四個正整數 x0, y0, x1, y1,表示插入一條兩個端點爲 ((x0+lastans-1)%39989+1,(y0+lastans-1)%10^9+1)和 ((x1+lastans-1)%39989+1,(y1+lastans-1)%10^9+1) 的線段
其中 lastans 爲上一次詢問的答案。初始時 lastans=0
輸出格式:
對於每一個 0 操做,輸出一行,包含一個正整數,表示交點最靠上的線段的編 號。若不存在與直線相交的線段,答案爲 0
對於 30%的數據,n ≤ 1000
對於 100%的數據,1 ≤ n ≤ 10^5, 1 ≤ k, x0, x1 ≤ 39989, 1 ≤ y0 ≤ y1 ≤ 10^9
題解Here!
看到這種題,直接上李超樹就好。
什麼?你不知道李超樹?
丟個連接:BZOJ1568: [JSOI2008]Blue Mary開公司
而後就能夠隨便跑了。
注:數據有毒,有某種數據是:$x_0==x_1,y_0!=y_1$
記得特判一下。。。
附代碼:
#include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1 #define RSON rt<<1|1 #define ID(x) a[x].id #define MUL(x) line[a[x].id].k #define ADD(x) line[a[x].id].b #define SIGN(x) a[x].c #define LSIDE(x) a[x].l #define RSIDE(x) a[x].r #define MAXN 100010 #define MODX 39989 #define MODY 1000000000 using namespace std; int n,num_line=0; struct Line{ double k,b; }line[MAXN]; struct Segment_Tree{ int id,l,r; bool c; }a[MAXN<<2]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline void add_line(double x1,double y1,double x2,double y2){ num_line++; if(x1!=x2){ line[num_line].k=(y1-y2)/(x1-x2); line[num_line].b=y1-x1*line[num_line].k; } else{ line[num_line].k=0; line[num_line].b=max(y1,y2); } } void buildtree(int l,int r,int rt){ LSIDE(rt)=l;RSIDE(rt)=r;ID(rt)=0;SIGN(rt)=false; if(l==r)return; int mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON); } void change(int id,int rt){ if(!SIGN(rt)){ SIGN(rt)=true; ID(rt)=id; return; } double l1=MUL(rt)*LSIDE(rt)+ADD(rt),l2=line[id].k*LSIDE(rt)+line[id].b; double r1=MUL(rt)*RSIDE(rt)+ADD(rt),r2=line[id].k*RSIDE(rt)+line[id].b; if(l1>=l2&&r1>=r2)return; else if(l1<l2&&r1<r2){ ID(rt)=id; return; } int mid=LSIDE(rt)+RSIDE(rt)>>1; double mid1=MUL(rt)*mid+ADD(rt),mid2=line[id].k*mid+line[id].b; if(l2>=l1){ if(mid2<mid1)change(id,LSON); else{ change(ID(rt),RSON); ID(rt)=id; } } else{ if(mid2<mid1)change(id,RSON); else{ change(ID(rt),LSON); ID(rt)=id; } } } void update(int l,int r,int id,int rt){ if(l<=LSIDE(rt)&&RSIDE(rt)<=r){ change(id,rt); return; } int mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)update(l,r,id,LSON); if(mid<r)update(l,r,id,RSON); } int query(int l,int r,int rt){ int ans=rt; if(l<=LSIDE(rt)&&RSIDE(rt)<=r)return rt; int mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid){ int id=query(l,r,LSON); double now=MUL(ans)*l+ADD(ans),Left=MUL(id)*l+ADD(id); if(now<Left)ans=id; else if(now==Left)ans=min(ans,id); } if(mid<r){ int id=query(l,r,RSON); double now=MUL(ans)*l+ADD(ans),Right=MUL(id)*l+ADD(id); if(now<Right)ans=id; else if(now==Right)ans=min(ans,id); } return ans; } void work(){ int last=0,f,x,x1,y1,x2,y2; while(n--){ f=read(); if(f){ x1=(read()+last-1+MODX)%MODX+1;y1=(read()+last-1+MODY)%MODY+1; x2=(read()+last-1+MODX)%MODX+1;y2=(read()+last-1+MODY)%MODY+1; if(x1>x2){swap(x1,x2);swap(y1,y2);} add_line(x1,y1,x2,y2); update(x1,x2,num_line,1); } else{ x=(read()+last-1)%MODX+1; last=query(x,x,1); last=ID(last); printf("%d\n",last); } } } void init(){ n=read(); buildtree(1,MODX+11,1); } int main(){ init(); work(); return 0; }