[Violet]天使玩偶/SJY擺棋子
阿新 • • 發佈:2018-12-09
max efi clear struct 排序 bool getchar() 一個 .org ,好像怎麽算都會超時……最後不得已之後不用\(sort\),改成用歸並排序之後還得開\(O2\)才能過。
傳送門
題目大意就是先給定n個點,然後m個操作,每次添加一個點或者查詢離一個點最近的一個點是哪個點。
因為要求的是曼哈頓距離,所以我們先把式子轉化一下,就是\((x_i + y_i) - (x_j + y_j)\),也就是對於查詢的點,求出時間早於它,且\(x,y\)都小於它的點中\(x_i+y_i\)最大的一個。這個可以用樹狀數組維護最大值。
這個就是很簡單的三維偏序,\(CDQ\)分治寫一下就好了。不過這樣只能找一個方向,一共有4個方向,每次用最大坐標分別減去橫,縱坐標就可以實現旋轉的效果了。
不過有點虛,這個理論的復雜度是\(O(4\times(n+m)log(n+m)logmax_y)\)
看一下代碼。
// luogu-judger-enable-o2 #include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<queue> #include<cstring> #define rep(i,a,n) for(register int i = a;i <= n;i++) #define per(i,n,a) for(register int i = n;i >= a;i--) #define enter putchar(‘\n‘) #define pr pair<int,int> #define mp make_pair #define fi first #define sc second #define lowbit(x) x & (-x) using namespace std; typedef long long ll; const int M = 300005; const int N = 1000005; inline int read() { int ans = 0,op = 1; char ch = getchar(); while(ch < ‘0‘ || ch > ‘9‘) { if(ch == ‘-‘) op = -1; ch = getchar(); } while(ch >=‘0‘ && ch <= ‘9‘) { ans *= 10; ans += ch - ‘0‘; ch = getchar(); } return ans * op; } inline void write(int x) { if(x < 0) x = -x, putchar(‘-‘); if(x >= 10) write(x / 10); putchar(x % 10 + ‘0‘); } struct treearray { int c[N+10]; void add(int x,int v) {while(x <= N+2) c[x] = max(c[x],v),x += lowbit(x);} int ask(int x) {int cur = 0;while(x) cur = max(cur,c[x]),x -= lowbit(x);return cur;} void clear(int x) {while(x <= N+2) c[x] = 0,x += lowbit(x);} }T; struct node { int x,y,tim; bool operator < (const node &g) const { return x < g.x; } }a[M<<1],b[M<<1],t[M<<1]; int n,m,cnt,op,Ti,ans[M]; void CDQ(int l,int r) { if(l == r) return; int mid = (l+r) >> 1,p1 = l,p2 = mid+1; CDQ(l,mid),CDQ(mid+1,r); //sort(a+l,a+mid+1),sort(a+mid+1,a+r+1); rep(i,l,r) { if(p2 > r || (p1 <= mid && a[p1].x <= a[p2].x)) { t[i] = a[p1++]; if(!t[i].tim) T.add(t[i].y,t[i].x + t[i].y); } else { t[i] = a[p2++]; if(!t[i].tim) continue; int k = T.ask(t[i].y); if(k) ans[t[i].tim] = min(ans[t[i].tim],t[i].x + t[i].y - k); } } rep(i,l,mid) if(!a[i].tim) T.clear(a[i].y); rep(i,l,r) a[i] = t[i]; } int main() { memset(ans,0x3f,sizeof(ans)); n = read(),m = read(); rep(i,1,n) b[++cnt].x = read()+1,b[cnt].y = read()+1; rep(i,1,m) { op = read(); if(op == 1) b[++cnt].x = read()+1,b[cnt].y = read()+1; else b[++cnt].x = read()+1,b[cnt].y = read()+1,b[cnt].tim = ++Ti; } rep(i,1,cnt) a[i] = b[i]; CDQ(1,cnt); rep(i,1,cnt) a[i] = b[i],a[i].x = N - a[i].x; CDQ(1,cnt); rep(i,1,cnt) a[i] = b[i],a[i].y = N - a[i].y; CDQ(1,cnt); rep(i,1,cnt) a[i] = b[i],a[i].x = N - a[i].x,a[i].y = N - a[i].y; CDQ(1,cnt); rep(i,1,Ti) write(ans[i]),enter; return 0; }
[Violet]天使玩偶/SJY擺棋子