[ 线段树 ] BZOJ3276

xiaoxiao2021-02-28  10

Source是骗人的。。树套树空间不够。。 将距离离散一下,建一棵线段树维护最小重力,一直扩展就好了。

#include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #include<cmath> #include<queue> using namespace std; inline char nc(){ static char buf[100000],*p1=buf,*p2=buf; return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++; } inline void Read(int& x){ char c=nc(),b=1; for(;c<'0'||c>'9';c=nc())if(c=='-')b=-1; for(x=0;c>='0'&&c<='9';x=(x<<3)+(x<<1)+c-48,c=nc());x*=b; } #define fi first #define se second typedef pair<int,int> abcd; const int N=250010; const int INF=2e9; abcd c[N<<1]; int pos[N],g[N],p[N],r[N]; int j,k,n,mxp,cnt; int x,y,pp,rr; int mn[N<<3],num; int q[N],L,R; priority_queue<abcd>w[N<<1]; inline double Dis(int a,int b){ return sqrt(1ll*(a-x)*(a-x)+1ll*(b-y)*(b-y)); } void Update(int x,int l,int r,int y,int z){ if(l==r){ w[l].push(abcd(-g[z],z));mn[x]=min(mn[x],g[z]); return; } int Mid=l+r>>1; if(y<=Mid)Update(x<<1,l,Mid,y,z); else Update(x<<1|1,Mid+1,r,y,z); mn[x]=min(mn[x<<1],mn[x<<1|1]); } void Query(int x,int l,int r,int y,int z){ if(l>y||mn[x]>z)return; if(l==r){ while(-w[l].top().fi<=z){ q[++R]=w[l].top().se; w[l].pop(); if(w[l].empty())break; } if(w[l].empty())mn[x]=INF;else mn[x]=-w[l].top().fi; return; } int Mid=l+r>>1; Query(x<<1,l,Mid,y,z);Query(x<<1|1,Mid+1,r,y,z); mn[x]=min(mn[x<<1],mn[x<<1|1]); } int main(){ Read(x);Read(y);Read(pp);Read(rr);Read(n); c[cnt=1].fi=rr;c[1].se=n*2+1; for(int i=1;i<=n;i++){ Read(j);Read(k);Read(g[i]);Read(p[i]);Read(c[++cnt].fi); c[cnt].se=i+n; c[++cnt].fi=ceil(Dis(j,k)); c[cnt].se=i; } sort(c+1,c+cnt+1); if(c[1].se>n)r[c[1].se-n]=mxp=1;else pos[c[1].se]=mxp=1; for(int i=2;i<=cnt;i++){ if(c[i].fi!=c[i-1].fi)mxp++; if(c[i].se>n)r[c[i].se-n]=mxp;else pos[c[i].se]=mxp; } memset(mn,127,sizeof(mn)); for(int i=1;i<=n;i++)Update(1,1,mxp,pos[i],i); L=R=0; Query(1,1,mxp,r[n+1],pp); while(++L<=R)Query(1,1,mxp,r[q[L]],p[q[L]]); cout<<R<<endl; return 0; }
转载请注明原文地址: https://www.6miu.com/read-2300187.html

最新回复(0)