• [BZOJ2648]SJY摆棋子


    bzoj

    题意

    平面上有(n)个点,每次往这个平面上加入一个点,或是询问离某个点最近点的距离。
    这里的距离指的是曼哈顿距离。

    sol

    (kd-Tree)了解一下?
    (O(nlog n))建树,然后(O(msqrt n))查询。
    插入导致树的不平衡?
    定期重构即可。

    code

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int gi()
    {
    	int x=0,w=1;char ch=getchar();
    	while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
    	if (ch=='-') w=0,ch=getchar();
    	while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
    	return w?x:-x;
    }
    #define cmin(a,b) (a>b?a=b:a)
    #define cmax(a,b) (a<b?a=b:a)
    #define ls t[o].ch[0]
    #define rs t[o].ch[1]
    #define inf 2147483647
    const int N = 5e5+5;
    int n,m,root,D,ans;
    struct node{
    	int d[2];
    	bool operator < (const node &b) const
    		{return d[D]<b.d[D];}
    }a[N];
    struct kdtree{int d[2],Min[2],Max[2],ch[2];}t[N<<1];
    void mt(int x,int y)
    {
    	cmin(t[x].Min[0],t[y].Min[0]);cmax(t[x].Max[0],t[y].Max[0]);
    	cmin(t[x].Min[1],t[y].Min[1]);cmax(t[x].Max[1],t[y].Max[1]);
    }
    int build(int l,int r,int d)
    {
    	D=d;int o=l+r>>1;
    	nth_element(a+l,a+o,a+r+1);
    	t[o].d[0]=t[o].Min[0]=t[o].Max[0]=a[o].d[0];
    	t[o].d[1]=t[o].Min[1]=t[o].Max[1]=a[o].d[1];
    	if (l<o) ls=build(l,o-1,d^1),mt(o,ls);
    	if (o<r) rs=build(o+1,r,d^1),mt(o,rs);
    	return o;
    }
    int dist(int o,int x,int y)
    {
    	return max(t[o].Min[0]-x,0)+max(x-t[o].Max[0],0)+max(t[o].Min[1]-y,0)+max(y-t[o].Max[1],0);
    }
    void query(int o,int x,int y)
    {
    	int tmp=abs(t[o].d[0]-x)+abs(t[o].d[1]-y),d[2];
    	if (ls) d[0]=dist(ls,x,y);else d[0]=inf;
    	if (rs) d[1]=dist(rs,x,y);else d[1]=inf;
    	cmin(ans,tmp);tmp=d[0]>=d[1];
    	if (d[tmp]<ans) query(t[o].ch[tmp],x,y);tmp^=1;
    	if (d[tmp]<ans) query(t[o].ch[tmp],x,y);
    }
    int main()
    {
    	n=gi();m=gi();
    	for (int i=1;i<=n;++i) a[i].d[0]=gi(),a[i].d[1]=gi();
    	root=build(1,n,0);
    	while (m--){
    		int op=gi(),x=gi(),y=gi();
    		if (op==1){
    			++n;
    			t[n].d[0]=t[n].Min[0]=t[n].Max[0]=x;
    			t[n].d[1]=t[n].Min[1]=t[n].Max[1]=y;
    			for (int p=root,d=0;p;d^=1)
    			{
    				mt(p,n);
    				int &nxt=t[p].ch[t[n].d[d]>=t[p].d[d]];
    				if (!nxt) {nxt=n;break;}p=nxt;
    			}
    		}
    		else{
    			ans=inf;query(root,x,y);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    欧拉函数 & 【POJ】2478 Farey Sequence & 【HDU】2824 The Euler function
    【BZOJ】2982: combination(lucas定理+乘法逆元)
    【vijos】1781 同余方程(拓展欧几里得)
    Disillusioning #1 水题+原题赛(被虐瞎)
    【HDU】3622 Bomb Game(2-SAT)
    小结:双连通分量 & 强连通分量 & 割点 & 割边
    【POJ】2942 Knights of the Round Table(双连通分量)
    【POJ】1523 SPF(割点)
    【POJ】1094 Sorting It All Out(拓扑排序)
    小结:网络流
  • 原文地址:https://www.cnblogs.com/zhoushuyu/p/8945805.html
Copyright © 2020-2023  润新知