Loading

noip模拟16

A. Star Way To Heaven

发现一个性质:对于每一个点来说,自身通过与上下边界连的边都会形成一道屏障.
考场上只考虑了三角形的情况,应该多画画图然后\(Hack\)自己的.
发现对于任意两点之间,要么选择经过一条与边界相连的边,要么经过这两个点之间的边.
于是可以考虑最小生成树,
之所以可以将其看成由图变成的树,是因为我们可以发现,这是一个需要遍历所有点且要经过较小值的边权.
关于为什么要遍历所有点,那是因为每个点至少要经过一个和其它点或和边界所连的边,即每个点都要造成贡献.
于是便显而易见了.

A_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define re register ll
#define lf double
#define mp make_pair
const ll N=6050;
inline void read(ll &ss)
{
	ss=0; bool cit=0; char ch;
	while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
	while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
	if(cit) ss=-ss;
}
ll n,m,alls;
lf ans;
ll vis[N],x[N],y[N];
lf dis[N];
lf getmax(lf i,lf j){ return i>j?i:j; }
lf getmin(lf i,lf j){ return i<j?i:j; }
lf getdis(ll i,ll j)
{
	ll temp1=abs(x[i]-x[j]),temp2=abs(y[i]-y[j]);
	ll temp=temp1*temp1+temp2*temp2; return sqrt(temp*1.0);
}
void prim()
{
	ans=-1.0;
	for(re i=1;i<=alls;i++)
	{
		ll x=0;
		for(re j=1;j<=alls;j++)
			if(vis[j]==0 and (x==0 or dis[j]<dis[x])) x=j;
		vis[x]=1; ans=getmax(ans,dis[x]);
		if(x==alls) break;
		for(re j=1;j<=alls-1;j++)
			if(vis[j]==0) dis[j]=getmin(dis[j],getdis(x,j));
		dis[alls]=getmin(dis[alls],y[x]);
	}
}
signed main()
{
	read(n); read(m); read(alls);
	for(re i=1;i<=alls;i++) { read(x[i]); read(y[i]); }
	alls++;  
	for(re i=1;i<=alls;i++) dis[i]=m-y[i];
	prim();
	printf("%.8lf",ans/2.0);
	return 0;
}

B. God Knows

裸的线段树维护单调栈,
也可以选择李超线段树.

B_code
#include<bits/stdc++.h>
using namespace std;
namespace BSS
{
	#define p() printf("Pass")
	#define ll int
	#define ull unsigned ll
	#define re register ll 
	#define lf double
	#define lb lower_bound 
	#define ub upper_bound 
	#define mp make_pair
	#define File(x,y) freopen(#x,"r",stdin),freopen(#y,"w",stdout)
	#define Fill(x,y) memset(x,y,sizeof x);
	#define Copy(x,y) memcpy(x,y,sizeof x);
	inline ll read()
	{
		ll ss=0; bool cit=1; char ch;
		while(!isdigit(ch=getchar())) if(ch=='-') cit=0;
		while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
		return cit?ss:-ss;
	}
	inline void write(ll ss)
	{
		static int stas[35]; int topps=0;
  		if(ss<0) putchar('-'),ss=-ss;
  		do{stas[++topps]=ss%10,ss/=10;}while(ss);
  		while(topps) putchar(stas[topps--]+48); puts("");
	}
} using namespace BSS;

const ll N=5e5+50;

ll m,n,lmt;
ll p[N],c[N],f[N],org[N];
struct I { ll l,r,maxn,sum,lv; } tr[N*64];
void build(ll x,ll l,ll r)
{	
	tr[x].l=l; tr[x].r=r;
	tr[x].lv=1e9; tr[x].sum=1e9;
	if(tr[x].l==tr[x].r) return ;
	ll mid=(l+r)>>1;
	build(x<<1,l,mid); build(x<<1|1,mid+1,r);
	return ;
}
ll calc(ll x,ll edge)
{
//	cout<<tr[x].maxn<<" "<<tr[x].sum<<" "<<edge<<endl;
	if(tr[x].l==tr[x].r) return tr[x].maxn>edge ? tr[x].sum : 1e9 ;
//	cout<<tr[x<<1|1].maxn<<" "<<edge<<" "<<tr[x].lv<<" "<<" skr\n";
	if(tr[x<<1|1].maxn>edge) return min(tr[x].lv,calc(x<<1|1,edge));
	else return calc(x<<1,edge);
}
void pushup(ll x)
{
	tr[x].sum=min(tr[x<<1].sum,tr[x<<1|1].sum);
	tr[x].maxn=max(tr[x<<1].maxn,tr[x<<1|1].maxn);
	tr[x].lv=calc(x<<1,tr[x<<1|1].maxn);
	return ;
}
void update(ll x,ll pos,ll maxn,ll sum)
{
	if(tr[x].l==tr[x].r)
	{
		tr[x].maxn=maxn;
		tr[x].sum=sum;
		return; 
	}
	ll mid=(tr[x].l+tr[x].r)>>1;
	if(pos<=mid) update(x<<1,pos,maxn,sum);
	else update(x<<1|1,pos,maxn,sum);
	pushup(x);
	return ;
}
ll query(ll x,ll ql,ll qr)
{
	if(ql>qr) return 1e9;
	ll temp; 
	if(tr[x].l>=ql and tr[x].r<=qr)
	{
//		if(ql==1 and qr==5) cout<<"Now:"<<lmt<<endl;
		temp=calc(x,lmt);
//		if(ql==1 and qr==5) cout<<"Finished."<<endl;
		lmt=max(lmt,tr[x].maxn);
		return temp;
	}
	ll mid=(tr[x].l+tr[x].r)>>1;
	temp=1e9;
	if(qr>=mid+1) temp=min(temp,query(x<<1|1,ql,qr));
	if(ql<=mid) temp=min(temp,query(x<<1,ql,qr));
	return temp;
}
	
signed main()
{
	n=read();
	for(re i=1;i<=n;i++) p[i]=read(),org[p[i]]=i;
	for(re i=1;i<=n;i++) c[i]=read();
	build(1,1,n);
	for(re i=1;i<=n;i++)
	{
		lmt=0;
		f[i]=query(1,1,p[i]-1)+c[i];
		if(f[i]>=1e9) f[i]=c[i];
		update(1,p[i],i,f[i]);
	}
	ll temp=0,ans=1e9;
	for(re i=n;i>=1;i--)
	{
		if(org[i]>temp) 
		{
			ans=min(ans,f[org[i]]),temp=max(temp,org[i]);
		}
	}
	write(ans);
	return 0;
}

C. Lost My Music

根据斜率计算即可.

C_code
#include<bits/stdc++.h>
using namespace std;
#define ll long long int
#define re register ll
#define lf double
#define mp make_pair
const ll N=1e6+50;
inline void read(ll &ss)
{
	ss=0; bool cit=0; char ch;
	while(!isdigit(ch=getchar())) if(ch=='-') cit=1;
	while(isdigit(ch)) ss=(ss<<3)+(ss<<1)+(ch^48),ch=getchar();
	if(cit) ss=-ss;
}
ll n,g,ts;
ll val[N],fa[N],f[N][30],head[N],dep[N],dfn[N],t[N];
lf ans[N];
struct I { ll u,v,nxt; } a[N];
inline void add(ll u,ll v)
{
	a[++ts].u=u;
	a[ts].v=v;
	a[ts].nxt=head[u];
	head[u]=ts;
}
lf C(ll a,ll b,ll c,ll d) 
{
	return (lf)(c-a)/(lf)(b*1.0-d*1.0);
}
void RMQ(ll &g,ll x)
{
	if(g>1)
	{
		for(re i=18;i>=0;i--)
		{
			if(f[g][i]>1)
			{
				ll v=f[g][i];
				if(C(val[v],dep[v],val[fa[v]],dep[fa[v]])<=C(val[v],dep[v],val[x],dep[x])) g=v;
			}
		}
		if(C(val[g],dep[g],val[fa[g]],dep[fa[g]])<=C(val[x],dep[x],val[g],dep[g])) g=fa[g];
	}
	fa[x]=f[x][0]=g;
	for(re i=1;i<=18;i++) f[x][i]=f[f[x][i-1]][i-1];
	g=x;
}
signed main()
{
	read(n); ll temp;
	for(ll i=1;i<=n;i++) read(val[i]);
	for(ll i=2;i<=n;i++) { read(temp); add(temp,i); }
	dep[1]=1; dfn[1]=1;
	for(ll st=1,alls=1;st<=alls;st++)
	{
		ll x=dfn[st],g=t[x];
		RMQ(g,x);
		if(x>1) ans[x]=C(val[g],dep[g],val[fa[g]],dep[fa[g]]);
		for(ll i=head[x];i;i=a[i].nxt)
		{
			dep[a[i].v]=dep[x]+1;
			dfn[++alls]=a[i].v;
			t[a[i].v]=g;
		}
	}
	for(ll i=2;i<=n;i++) printf("%0.8lf\n",ans[i]);
}
posted @ 2021-08-05 19:51  AaMuXiiiiii  阅读(53)  评论(0)    收藏  举报