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

Luogu4169

每次操作加入平面上一个点 , 或者询问离一个点最近的点的距离

CDQ分治模板
\(1.\)solve(l,mid);
\(2.\)solve(mid+1,r);
\(3.\)计算\([l,mid]\)中修改操作对\([mid+1,r]\)中查询操作的影响

/*
----------------------
[CDQ分治] 天使玩偶
1.solve(l,mid);
2.solve(mid+1,r);
3.计算[l,mid]中修改操作对[mid+1,r]中查询操作的影响
----------------------
对于这道题:
假设只有修改,题目变成每次只有查询,询问到某个点最近的点距离:
ans=Min(|X-x[i]|+|Y-y[i]|)
对于绝对值,把它拆成四次解决.
对于左下角的点:ans=X+Y-Max(x[i]+y[i])
按x坐标排序满足了x[i]<=X的条件,BIT控制了y[i]<=Y的条件并维护了x[i]+y[i]的最大值
对于左上角的点:ans=X-Y+Min(y[i]-x[i])=X-Y+Max(x[i]-y[i])
具体四个方向的实现见李煜东的神奇操作
----------------------2018.12.26
*/
#include<bits/stdc++.h>
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
using namespace std;
typedef long long LL;
const int INF=1e9+7;
inline LL read(){
    register LL x=0,f=1;register char c=getchar();
    while(c<48||c>57){if(c=='-')f=-1;c=getchar();}
    while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar();
    return f*x;
}

const int MAXN=1000005;

struct Node{
    int x,y,z;
    inline friend bool operator < (Node a,Node b){
        if(a.x==b.x) return a.y<b.y;
        return a.x<b.x;
    }
}a[MAXN],b[MAXN];

namespace BIT{
    int c[MAXN],Ctot;
    inline void insert(int x,int val){
        for(;x<Ctot;x+=x&-x) c[x]=Max(c[x],val);//前缀最大值
        //由于Ctot加了1,所以实际的Ctot没有到这么大(但Ctot对于query没有影响,所以加上等号也不会错)
    }
    inline int query(int x){
        int res=-(1<<30);
        for(;x;x-=x&-x) res=Max(res,c[x]);
        return res;
    }
    inline void cancel(int x){
        for(;x<Ctot;x+=x&-x) c[x]=-(1<<30);//全部赋为最小值
    }
}using namespace BIT;

int ans[MAXN];
int n,m;

// 求解简化版问题,需要考虑b[st~ed]的坐标,根据4个方向的不同,
// 横坐标顺序为de(±1),树状数组维护的信息用系数dx,dy(±1)指定
inline void cal(int st,int ed,int sign,int dx,int dy){
    for(int i=st;i!=ed;i+=sign){
        int y=dy==1?b[i].y:Ctot-b[i].y;//由于-b[i].y是负数,所以加上一个大数
        int val=dx*b[i].x+dy*b[i].y;
        if(a[b[i].z].z==1) insert(y,val);
        else ans[b[i].z]=Min(ans[b[i].z],abs(val-query(y)));
        //注意:query(y)并不就是答案,答案是(形如x[i]+y[i])与query(y)的差
    }
    for(int i=st;i!=ed;i+=sign){
        int y=dy==1?b[i].y:Ctot-b[i].y;
        if(a[b[i].z].z==1) cancel(y);//撤销修改
    }
}

inline void CDQ(int l,int r){
    int mid=(l+r)>>1;
    if(l<mid) CDQ(l,mid);
    if(mid+1<r) CDQ(mid+1,r);
    int t=0;
    for(int i=l;i<=r;i++){
        if(i<=mid&&a[i].z==1||i>mid&&a[i].z==2)
            b[++t]=a[i],b[t].z=i;
    }
    sort(b+1,b+t+1);
    cal(1,t+1,1,1,1);cal(t,0,-1,-1,-1);
    cal(1,t+1,1,1,-1);cal(t,0,-1,-1,1);
}

int main(){
    n=read(),m=read(),m+=n;
    for(int i=1;i<=n;i++)
        a[i].x=read(),a[i].y=read()+1,a[i].z=1;//注意:y坐标要加1,否则BIT会出错
    for(int i=n+1;i<=m;i++)
        a[i].z=read(),a[i].x=read(),a[i].y=read()+1;
    for(int i=1;i<=m;i++)
        Ctot=Max(Ctot,a[i].y);
    Ctot++;//同样要加1,应对y=Ctot-b[i].z的情况
    memset(c,0xcf,sizeof c);
    memset(ans,0x3f,sizeof ans);
    CDQ(1,m);
    for(int i=1;i<=m;i++)
        if(a[i].z==2) printf("%d\n",ans[i]);
}

代码重构于19.4.3

原文地址:https://www.cnblogs.com/lizehon/p/10647920.html

时间: 2024-10-09 15:06:45

[Violet]天使玩偶/SJY摆棋子的相关文章

[Luogu4169][Violet]天使玩偶/SJY摆棋子

luogu 题意 一个平面上有\(n\)个点,\(m\)次操作,每次新增一个点,或者是询问离某个点最近的点的距离.这里的距离是曼哈顿距离. \(n,m\le3*10^5\) sol 写一发\(CDQ\). 只考虑询问点在其他点的右上方的情况,假设询问点是\(A\),那么所求的距离就是\((X_A-X_i)+(Y_A-Y_i)=(X_A+Y_A)-(X_i+Y_i)\). 所以我们只需要找出满足\(X_i \le X_A,Y_i \le Y_A\)中\(X_i+Y_i\)的最大值就好了. \(CD

Luogu P4169 [Violet]天使玩偶/SJY摆棋子

传送门 二维平面修改+查询,cdq分治可以解决. 求关于某个点曼哈顿距离(x,y坐标)最近的点——dis(A,B) = |Ax-Bx|+|Ay-By| 但是如何去掉绝对值呢? 查看题解发现假设所有的点都在查询点的左下方,dis(A,B) = (Ax-Bx)+(Ay-By) = (Ax+Ay)-(Bx+By) 只要求满足Bx<Ax,By<Ay且Bx,By之和最大的点就好了. 那么如何把所有的点转化到该查询的左下呢? 对于每个查询,可以把一.二.四象限的点都通过对称转移到第三象限.但查询很多,不可

P4169 [Violet]天使玩偶/SJY摆棋子

1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<iostream> 4 using namespace std; 5 const int maxn=1e7+10; 6 const int inf=2e7+7; 7 struct node 8 { 9 int x,y,id,ans,time; 10 }a[maxn],b[maxn],tt[maxn];; 11 int flag; 12 int len,x,y; 13

【bzoj2648&amp;bzoj2716】[Violet3]天使玩偶&amp;SJY摆棋子【kd树】

1BK捌脊允4iyo松纲06http://weibo.com/u/6264971116 382u60L86vl戎导屯http://www.docin.com/nqra496 u23j6h0敢d缴遮ahttp://www.facebolw.com/space/2104191 86褐2咕6镜y米0uhttp://huiyi.docin.com/sina_6352810924 160hA坷Yk闭苫6尾ehttp://shequ.docin.com/sina_6267166088 侍4E0pf范星17南

SJY摆棋子&amp;&amp;[Violet 3]天使玩偶

SJY摆棋子 https://www.lydsy.com/JudgeOnline/problem.php?id=2648 [Violet 3]天使玩偶 https://www.lydsy.com/JudgeOnline/problem.php?id=2716 参考博客:https://blog.csdn.net/Littlewhite520/article/details/78284697 KDtree模板题,带插入 1 #include<iostream> 2 #include<cst

【BZOJ-2648&amp;2716】SJY摆棋子&amp;天使玩偶 KD Tree

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MBSubmit: 2459  Solved: 834[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=500000

BZOJ 2648(SJY摆棋子-KD_Tree)

2648: SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB Submit: 1180  Solved: 391 [Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N<=5000

【BZOJ2648】SJY摆棋子 [KD-tree]

SJY摆棋子 Time Limit: 20 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description 这天,SJY显得无聊.在家自己玩.在一个棋盘上,有N个黑色棋子.他每次要么放到棋盘上一个黑色棋子,要么放上一个白色棋子,如果是白色棋子,他会找出距离这个白色棋子最近的黑色棋子.此处的距离是 曼哈顿距离 即(|x1-x2|+|y1-y2|) .现在给出N个初始棋子,和M个操作.对于每个白色棋子,输出距离这个白色棋子最近的黑色棋子的

BZOJ 2648 SJY摆棋子 / 2716 Violet 3 天使玩偶 K-D树

题目大意:平面上有一些点,问一个点周围离它最近的点的曼哈顿距离是多少.支持动态加点. 思路:CDQ分治可以离线解决,但是SJY是卡CDQ的,天使玩偶可以过.毕竟K-D树的O(sqrt(n))的时间复杂度摆在那. K-D树理解起来其实不难,有k个维度的时候,每一层按照一个维度排序,取出按照这个维度排序的中位数,当作这个块的根,然后将这个块分开.还有一个比较重要的东西就是估价函数,这个函数根据不同的题可能不同.股价函数的主要用途就是对搜索进行剪枝,如果估价函数就已经大于当前的最优答案了,那就不用搜这