• CH#46A 磁力块


    https://www.acwing.com/problem/content/252/

    https://ac.nowcoder.com/acm/contest/1034/B

    题目

    在一片广袤无垠的原野上,散落着N块磁石。

    每个磁石的性质可以用一个五元组(x,y,m,p,r)描述,其中x,y表示其坐标,m是磁石的质量,p是磁力,r是吸引半径。

    若磁石A与磁石B的距离不大于磁石A的吸引半径,并且磁石B的质量不大于磁石A的磁力,那么A可以吸引B。

    小取酒带着一块自己的磁石L来到了这片原野的(x0,y0)处,我们可以视磁石L的坐标为(x0,y0)。

    小取酒手持磁石L并保持原地不动,所有可以被L吸引的磁石将会被吸引过来。

    在每个时刻,他可以选择更换任意一块自己已经获得的磁石(当然也可以是自己最初携带的L磁石)在(x0,y0) 处吸引更多的磁石。

    小取酒想知道,他最多能获得多少块磁石呢?

    $1leqslant Nleqslant 250000$

    $−10^9leqslant x,yleqslant10^9$

    $1leqslant m,p,rleqslant10^9$

    题解

    这是个需要二维查询的题目,首先可以BFS。因为是分块例题= =

    分块方法为:先将整个区间按照质量排序,分为D块,再把D块内按照距离排序

    第一维用O(D)的时间找到所有质量都小于等于吸力的块,第二维每一块都顺序遍历确定距离比半径小的,并且保证每一个只遍历一次(因为距离已经排好了)

    剩下的块直接遍历。

    每个元素只遍历一次,但是在bfs的每一步,每个块都要遍历一次,还要考虑剩下的块,所以时间复杂度是$mathcal{O}(n imes (1+n/D+D))$,为了不升阶,可以取$D=sqrt{n}$

    AC代码

    #include<bits/stdc++.h>
    using namespace std;
    #define REP(i,a,b) for(register int i=(a); i<(b); i++)
    #define REPE(i,a,b) for(register int i=(a); i<=(b); i++)
    #define PERE(i,a,b) for(register int i=(a); i>=(b); i--)
    #ifdef sahdsg
    #define DBG(...) printf(__VA_ARGS__)
    #else
    #define DBG(...) void(0)
    #endif
    typedef long long ll;
    #define MAXN 250007
    
    struct node{
    	int m,p;
    	ll dis, r;
    };
    bool cmp1(const node&l, const node&r) {
    	return l.m<r.m;
    }
    bool cmp2(const node&l, const node&r) {
    	return l.dis<r.dis;
    }
    int D,L;
    node arr[MAXN]; int M[MAXN];
    int pos[MAXN],ed[MAXN];
    #define x0 fadfjklwa
    #define y0 jfdalskas
    int x0,y0,pl,n;
    ll rl;
    int ans;
    queue<int> q;
    bool vis[MAXN];
    void go() {
    	ans=0;
    	q.push(-1);
    	REP(i,0,n) {
    		vis[i]=0;
    	}
    	while(!q.empty()) {
    		int now=q.front(); q.pop(); 
    		if(~now) {
    			pl = arr[now].p;
    			rl = arr[now].r;
    		}
    		int i=0;
    		for(;i<D &&M[i]<=pl;i++) {
    			for(;pos[i]<ed[i] && arr[pos[i]].dis<=rl; pos[i]++) if(!vis[pos[i]]){
    				vis[pos[i]]=1; 
    				ans++;
    				q.push(pos[i]);
    			}
    		}
    		if(i<D) {
    			REP(j,pos[i],ed[i]) if(!vis[j]) {
    				if(arr[j].dis<=rl && arr[j].m<=pl) {
    					vis[j]=1; 
    					ans++;
    					q.push(j);
    				}
    			}
    		}
    	}
    	
    }
    int main() {
    	scanf("%d%d%d%lld%d", &x0, &y0, &pl, &rl, &n);rl*=rl;
    	REP(i,0,n) {
    		ll x,y;
    		int m,p,r;
    		scanf("%lld%lld%d%d%d", &x, &y, &m, &p, &r);
    		x-=x0, y-=y0;
    		arr[i]=(node){m,p,x*x+y*y,(ll)r*r};
    	}
    	sort(arr,arr+n,cmp1);
    	L=sqrt((double)n); if(L==0) L=1;
    	D=n/L; pos[0]=0;
    	REP(i,0,D) {
    		ed[i]=pos[i+1]=pos[i]+L;
    		M[i]=arr[ed[i]-1].m; 
    		sort(arr+pos[i], arr+ed[i],cmp2);
    	}
    	if(pos[D]<n) {
    		ed[D]=n;
    		M[D]= arr[n-1].m;
    		sort(arr+pos[D], arr+ed[D],cmp2);
    		
    		pos[++D]=n;
    	}
    	go();
    	printf("%d
    ", ans);
    }
    
  • 相关阅读:
    (U3D)Time的使用
    (U3D)如何从RESOURCES文件夹动态加载图片
    codeforce 3C-3D(Greedy)
    codeforce 3A-3B(Greedy)
    读取bmp
    透视投影的原理和实现-转载
    Drainage Ditches USACO 4.2 (最大流,BFS)
    成员函数指针小记-转载
    codeforce 2A-2B
    字符串各种Hash算法比较-转载
  • 原文地址:https://www.cnblogs.com/sahdsg/p/12080068.html
Copyright © 2020-2023  润新知