1. 程式人生 > >[Violet]天使玩偶/SJY擺棋子

[Violet]天使玩偶/SJY擺棋子

max efi clear struct 排序 bool getchar() 一個 .org

傳送門

題目大意就是先給定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)\)

,好像怎麽算都會超時……最後不得已之後不用\(sort\),改成用歸並排序之後還得開\(O2\)才能過。

看一下代碼。

// 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擺棋子