帶你精通Python正則表示式
阿新 • • 發佈:2021-08-31
李超線段樹
用途:給定 $\mathrm{n}$ 個 $\mathrm{y}=\mathrm{kx}+\mathrm{b}$ 形式的線段,問 $\mathrm{x}=\mathrm{x[0]}$ 與哪條線段交點的縱座標值最大.
對於李超樹的每一個區間,維護這條區間的 “優勢線段”,即區間 $\mathrm{mid}$ 位置上縱座標最大的線段.
當在區間中插入一條線段時,按照下列步驟:
1. 若新插入線段中點位置大於當前線段,則該區間的優勢線段更新為新線段,並將當前線段向下遞迴更新.
2. 若將遞迴更新的線段左/右端點的值小於優勢線段,顯然會完全被覆蓋掉,就沒有必要繼續遞迴了.
3. 若滿足遞迴條件,則遞迴繼續更新.
插入線段時間複雜度為 $O(n \log ^2 n)$,查詢複雜度為 $O(n \log n)$.
Segment
來源:洛谷P4097 [HEOI2013]Segment
模板題,注意線段的 $\mathrm{x[0]}=\mathrm{x[1]}$ 時將斜率取為 $0$ 即可.
#include <cstdio> #include <cstring> #include <cmath> #include <vector> #include <set> #include <algorithm> #define M 50003 #define N 100009 #define ll long long #define pb push_back #define ls (now<<1) #define rs (now<<1|1) #define setIO(s) freopen(s".in","r",stdin) using namespace std; const int mod=39989; const double eps=1e-8; int tree[N<<2]; struct seg { double k,b; seg(double i=0.0,double j=0.0) { k=i,b=j;} }s[N]; double calc(seg o, int x) { return o.k*x+o.b; } void modify(int l,int r,int now,int L,int R,int x) { int mid=(l+r)>>1; if(l>=L&&r<=R) { if(calc(s[x],mid)-calc(s[tree[now]],mid)>eps) swap(x, tree[now]); if(calc(s[x],l)-calc(s[tree[now]],l)>eps) modify(l,mid,ls,L,R,x); if(calc(s[x],r)-calc(s[tree[now]],r)>eps) modify(mid+1,r,rs,L,R,x); return ; } if(L<=mid) modify(l,mid,ls,L,R,x); if(R>mid) modify(mid+1,r,rs,L,R,x); } void upd(int &x,int o,int p) { double yx=s[x].k*p+s[x].b; double yo=s[o].k*p+s[o].b; if(yo-yx>=eps||(abs(yo-yx)<=eps&&o<x)) x=o; } int query(int l,int r,int now,int p) { if(l==r) { return tree[now]; } int mid=(l+r)>>1,id=tree[now]; if(p<=mid) upd(id, query(l,mid,ls,p), p); else upd(id, query(mid+1,r,rs,p), p); return id; } int main() { // setIO("input"); // freopen("input.out","w",stdout); int Q,lastans=0,n=0; scanf("%d",&Q); while(Q--) { int op; scanf("%d",&op); if(op==0) { int k,x; scanf("%d",&k); k=(k+lastans-1)%mod+1; printf("%d\n",lastans=query(1,M,1,k)); } else { int x[2],y[2]; scanf("%d%d%d%d",&x[0],&y[0],&x[1],&y[1]); x[0]=(x[0]+lastans-1)%mod+1; y[0]=(y[0]+lastans-1)%1000000000+1; x[1]=(x[1]+lastans-1)%mod+1; y[1]=(y[1]+lastans-1)%1000000000+1; if(x[0]==x[1]) { s[++n].k=0,s[n].b=max(y[0], y[1]); } else { s[++n].k=(double)1.0*(y[1]-y[0])/(x[1]-x[0]); s[n].b=y[0]-1.0*s[n].k*x[0]; } if(x[0]>x[1]) swap(x[0],x[1]); modify(1,M,1,x[0],x[1],n); } } return 0; }