#cdq分治,樹狀陣列#洛谷 4169 [Violet]天使玩偶/SJY擺棋子
阿新 • • 發佈:2020-08-09
分析
首先如果不會\(\text{K-DTree}\)的話,那就用CDQ分治吧
這題首先要去絕對值,分四種情況討論, 只判斷左下角的點
然後考慮怎樣求最大值,這裡採用樹狀陣列,反正只是單點修改單點查詢,
而且樹狀陣列常數小,可以用樹狀陣列實現,下標為縱座標,存入橫縱座標之和
類似於歸併排序的方法按照橫座標排序,處理\([l,mid]\)的區間來解決\([mid+1,r]\)的問題
程式碼
#include <cstdio> #include <cctype> #include <cstring> #define rr register using namespace std; const int N=600011; bool nee[N]; struct rec{int x,y,rk; bool ne;}Q[N<<1],q[N]; int c[N<<1],ans[N],mx,my,mmx,mmy,n,m; inline signed iut(){ rr int ans=0; rr char c=getchar(); while (!isdigit(c)) c=getchar(); while (isdigit(c)) ans=(ans<<3)+(ans<<1)+(c^48),c=getchar(); return ans; } inline void print(int ans){ if (ans>9) print(ans/10); putchar(ans%10+48); } inline void Min(int &a,int b){if (a>b) a=b;} inline void Max(int &a,int b){if (a<b) a=b;} inline void updzro(int x){for (;x<=mmy;x+=-x&x) if (c[x]) c[x]=0; else return;} inline void update(int x,int y){for (;x<=mmy;x+=-x&x) Max(c[x],y);} inline signed query(int x){rr int ans=0; for (;x;x-=-x&x) Max(ans,c[x]); return ans;} inline void CDQ(int l,int r){ if (l==r) return; rr int mid=(l+r)>>1,j=l; CDQ(l,mid),CDQ(mid+1,r); for (rr int i=mid+1;i<=r;++i) if (Q[i].ne){ for (;j<=mid&&Q[j].x<=Q[i].x;++j) if (!Q[j].ne) update(Q[j].y,Q[j].x+Q[j].y); rr int t=query(Q[i].y); if (t) Min(ans[Q[i].rk],Q[i].x+Q[i].y-t); } for (rr int i=l;i<j;++i) if (!Q[i].ne) updzro(Q[i].y); rr int i1=l,j1=mid+1,cnt=0; for (;i1<=mid&&j1<=r;) if (Q[i1].x<=Q[j1].x) q[++cnt]=Q[i1],++i1; else q[++cnt]=Q[j1],++j1; for (;i1<=mid;++i1) q[++cnt]=Q[i1]; for (;j1<=r;++j1) q[++cnt]=Q[j1]; for (rr int i=l;i<=r;++i) Q[i]=q[i-l+1]; } inline void Clear(bool ne1,bool ne2){ mmx=mmy=m=0; rr rec T; for (rr int i=1;i<=n;++i) Q[i]=Q[i+n]; if (ne1) for (rr int i=1;i<=n;++i) Q[i].x=mx-Q[i].x+1; if (ne2) for (rr int i=1;i<=n;++i) Q[i].y=my-Q[i].y+1; for (rr int i=1;i<=n;++i) if (Q[i].ne) Max(mmx,Q[i].x),Max(mmy,Q[i].y); for (rr int i=1;i<=n;++i) if (Q[i].x<=mmx&&Q[i].y<=mmy) T=Q[++m],Q[m]=Q[i],Q[i]=T; } signed main(){ n=iut(),m=iut(),memset(ans,42,sizeof(ans)); for (rr int i=1;i<=n;++i){ rr int x=iut()+1,y=iut()+1; Q[i]=(rec){x,y,i,0},Max(mx,x),Max(my,y); nee[i]=0; } while (m--){ rr int z=iut()-1,x=iut()+1,y=iut()+1; Q[++n]=(rec){x,y,n,z},Max(mx,x),Max(my,y),nee[n]=z; } for (rr int i=1;i<=n;++i) Q[i+n]=Q[i]; Clear(0,0),CDQ(1,m),Clear(1,0),CDQ(1,m), Clear(0,1),CDQ(1,m),Clear(1,1),CDQ(1,m); for (rr int i=1;i<=n;++i) if (nee[i]) print(ans[i]),putchar(10); return 0; }