bzoj3165 [Heoi2013]Segment
题目描述:
题解:
李超线段树模板题.
用一棵线段树去维护完全覆盖当前区间的所有线段中较优的一条,
怎么叫较优?意思是当出现两线段在区间中点相交时,我们记录一条就好,另一条向下传递更新子区间.
代码:
#include<cmath> #include<cstdio> #include<cstring> #include<algorithm> using namespace std; const int N = 100050; const int M = 40050; const int MAX = 40000; const int MOD = 39989; const int MDD = 1000000007; const double eps = 1e-6; template<typename T> inline void read(T&x) { T f = 1,c = 0;char ch=getchar(); while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} while(ch>='0'&&ch<='9'){c=c*10+ch-'0';ch=getchar();} x = f*c; } struct Line { double k,b; Line(){k=b=0;} Line(double k,double b):k(k),b(b){} Line(double x_1,double y_1,double x_2,double y_2) { if(x_1!=x_2) { k = (y_1-y_2)/(x_1-x_2); b = y_1 - k*x_1; }else k=0,b=y_1; } double c(double x){return k*x+b;} }e[N]; int n,ans; struct lctree { int nam[M<<2]; void insert(int l,int r,int u,int ql,int qr,int k) { if(l==ql&&r==qr) { if(!nam[u]){nam[u]=k;return ;} double e0l = e[nam[u]].c(l),e0r = e[nam[u]].c(r); double e1l = e[k].c(l),e1r = e[k].c(r); if(e0l+eps<e1l&&e0r+eps<e1r){nam[u]=k;return ;} else if(e1l+eps<=e0l&&e1r+eps<=e0r)return ; int mid = (l+r)>>1; if(e[nam[u]].c(mid)+eps<e[k].c(mid)) { insert(l,mid,u<<1,ql,mid,k); insert(mid+1,r,u<<1|1,mid+1,qr,k); }else { if(e0l+eps<e1l)insert(l,mid,u<<1,ql,mid,k); else insert(mid+1,r,u<<1|1,mid+1,qr,k); } return ; } int mid = (l+r)>>1; if(qr<=mid)insert(l,mid,u<<1,ql,qr,k); else if(ql>mid)insert(mid+1,r,u<<1|1,ql,qr,k); else insert(l,mid,u<<1,ql,mid,k),insert(mid+1,r,u<<1|1,mid+1,qr,k); } void query(int l,int r,int u,int qx) { if(nam[u]) if(!ans||e[ans].c(qx)+eps<e[nam[u]].c(qx)||(ans>nam[u]&&fabs(e[nam[u]].c(qx)-e[ans].c(qx))<=eps))ans = nam[u]; if(l==r)return ; int mid = (l+r)>>1; if(qx<=mid)query(l,mid,u<<1,qx); else query(mid+1,r,u<<1|1,qx); } }tr; int main() { // freopen("tt.in","r",stdin); read(n); for(int op,x_1,y_1,x_2,y_2,k,tot=0,i=1;i<=n;i++) { read(op); if(!op) { read(k),k = (k+ans-1)%MOD+1; ans = 0;tr.query(0,MAX,1,k); printf("%d\n",ans); }else { read(x_1),read(y_1),read(x_2),read(y_2); x_1 = (x_1%MOD+ans-1)%MOD+1; y_1 = (y_1%MDD+ans-1)%MDD+1; x_2 = (x_2%MOD+ans-1)%MOD+1; y_2 = (y_2%MDD+ans-1)%MDD+1; if(x_1>x_2)swap(x_1,x_2),swap(y_1,y_2); if(x_1==x_2) { if(y_1>y_2)y_2=y_1; else y_1=y_2; } e[++tot] = Line(x_1,y_1,x_2,y_2); tr.insert(0,MAX,1,x_1,x_2,tot); } } return 0; }