bzoj 2716 [Violet 3]天使玩偶 【CDQ分治】

 KD-tree可做,但是 我不会暂时不考虑

大意:在二维平面内,给定n个点,m个操作。操作A:加入一个点;操作B:询问一个点与平面上加入的点的最近距离

不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T不封装会T

把初始存在的点也看成加点操作

首先,曼哈顿距离取绝对值很烦,所以我们可以通过转坐标,把左上 右上 左下 右下通过转坐标都变成左下,最后取个min即可。于是对于(x,y)左下的点(x1,y1),dis=x-x1+y-y1=(x+y)-(x1+y1),用树状数组维护前缀最小值x1+y1。

按时间序排列,时间序 x y 三维偏序做CDQ分治即可

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<algorithm>
  4 using namespace std;
  5 const int N=1000005,inf=1e9;
  6 int n,m,maxx,ans[N];
  7 struct BIT
  8 {
  9     int c[N];
 10     int lb(int x)
 11     {
 12         return x&(-x);
 13     }
 14     void update(int x,int d)
 15     {
 16         for(int i=x;i<=maxx;i+=lb(i))
 17             c[i]=max(c[i],d);
 18     }
 19     int ques(int x)
 20     {
 21         int ret=0;
 22         for(int i=x;i>=1;i-=lb(i))
 23             ret=max(ret,c[i]);
 24         return ret;
 25     }
 26     void clear(int x)
 27     {
 28         for(int i=x;i<=maxx;i+=lb(i))
 29             c[i] = 0;
 30     }
 31 }bit;
 32 struct qwe
 33 {
 34     int x,y,k,id;
 35     bool operator < (const qwe& rhs) const
 36     {
 37         if(x != rhs.x)
 38             return x < rhs.x;
 39         return id < rhs.id;
 40     }
 41 }a[N];
 42 struct CDQ
 43 {
 44     int n;
 45     qwe T[N];
 46     void init(int n)
 47     {
 48         this->n=n;
 49         sort(a+1,a+n+1);
 50     }
 51     void solve(int L, int R)
 52     {
 53         if(L>=R)
 54             return;
 55         int M=(L+R)>>1;
 56         int p=L,q=M+1;
 57         for(int i=L;i<=R;i++)
 58             if(a[i].id<=M)
 59                 T[p++]=a[i];
 60             else
 61                 T[q++]=a[i];
 62         for(int i=L;i<=R;i++)
 63             a[i]=T[i];
 64         solve(L,M);
 65         solve(M+1,R);
 66         int i=M+1,j=L;
 67         for(;i<=R;i++)
 68             if(a[i].k==2)
 69             {
 70                 for(;j<=M&&a[j].x<=a[i].x;j++)
 71                     if(a[j].k==1)
 72                         bit.update(a[j].y,a[j].x+a[j].y);
 73                 int t=bit.ques(a[i].y);
 74                 if(t)
 75                     ans[a[i].id]=min(ans[a[i].id],a[i].x+a[i].y-t);
 76             }
 77         for(int i=L;i<j;i++)
 78             if(a[i].k==1)
 79                 bit.clear(a[i].y);
 80         merge(a+L,a+M+1,a+M+1,a+R+1,T+L);
 81         for(int i=L;i<=R;i++)
 82             a[i]=T[i];
 83     }
 84 }cdq;
 85 int read()
 86 {
 87     int r=0;
 88     char p=getchar();
 89     while(p>'9'||p<'0')
 90         p=getchar();
 91     while(p>='0'&&p<='9')
 92     {
 93         r=r*10+p-48;
 94         p=getchar();
 95     }
 96     return r;
 97 }
 98 int main()
 99 {
100     n=read(),m=read();
101     for(int i=1;i<=n;i++)
102     {
103         a[i].x=read()+1;
104         a[i].y=read()+1;
105         a[i].id=i;
106         a[i].k=1;
107         maxx=max(maxx,max(a[i].x,a[i].y));
108     }
109     for(int i=n+1;i<=n+m;i++)
110     {
111         a[i].k=read();
112         a[i].x=read()+1;
113         a[i].y=read()+1;
114         a[i].id=i;
115         maxx=max(maxx,max(a[i].x,a[i].y));
116     }
117     maxx++;
118     n+=m;
119     for(int i=1;i<=n;i++)
120         ans[i]=inf;
121     cdq.init(n);
122     cdq.solve(1,n);
123     for(int i=1;i<=n;i++)
124         a[i].x=maxx-a[i].x;
125     cdq.init(n);
126     cdq.solve(1,n);
127     for(int i=1;i<=n;i++)
128         a[i].y=maxx-a[i].y;
129     cdq.init(n);
130     cdq.solve(1,n);
131     for(int i=1;i<=n;i++)
132         a[i].x=maxx-a[i].x;
133     cdq.init(n);
134     cdq.solve(1,n);
135     for(int i=1;i<=n;i++)
136         if(ans[i]!=inf)
137             printf("%d\n",ans[i]);
138     return 0;
139 }

 

转载于:https://www.cnblogs.com/lokiii/p/8108636.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值