T1

是我早就忘干净的最小生成树...(特殊生成树,欧几里得生成树)

用一手prim算法一直连最小距离边

连到\(k+1\)(边界)退出即可。

Code

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline db min(db a,db b){return a<b?a:b;}inline db max(db a,db b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	const int N=6050;
	int n,m,k,x[N],y[N],v[N];db ans,dis[N];
	inline db len(int x,int y,int a,int b){
		return sqrt(1ll*(a-x)*(a-x)+1ll*(b-y)*(b-y));
	}
	inline short main(){
		n=read(),m=read(),k=read();
		F(i,1,k){
			x[i]=read(),y[i]=read();
			dis[i]=y[i];
		}dis[k+1]=m;
		while(1){
			int mi=0;
			F(i,1,k+1)
				if(!v[i]&&(!mi||dis[i]<dis[mi]))
					mi=i;
			ans=max(ans,dis[mi]);
			if(mi==k+1){
				pf("%.10lf",ans/2);
				return 0;
			}
			F(i,1,k)dis[i]=min(dis[i],len(x[i],y[i],x[mi],y[mi]));
			dis[k+1]=min(dis[k+1],m-y[mi]);v[mi]=1;
		}
		return 0;
	}
}
signed main(){return EMT::main();}
T2

用一手神仙线段树...

\(f\),\(mf\),\(mx\)分别代表最小权值,左子树在右子树限制下的最小权值,最大的限制\(i\)

\(1\)\(n\)依次插入即可。

Code

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	typedef long long ll;//(double)clock() / (double)CLOCKS_PER_SEC;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline int min(int a,int b){return a<b?a:b;}inline int max(int a,int b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	const int N=2e5+100,inf=2e9;
	int n,p[N],c[N],rmax,an=2e9,f[N];
	struct tree{int mx,f,mf;}t[N<<2];
	inline int query(int p,int l,int r,int ql,int qr,int v){
		if(t[p].mx<v)return inf;
		if(l==r){rmax=max(rmax,t[p].mx);return t[p].f;}
		int mid=(l+r)>>1;
		if(l==ql&&r==qr){
			if(t[p<<1|1].mx<v)return query(p<<1,l,mid,ql,mid,v);
			rmax=max(rmax,t[p].mx);
			return min(t[p].mf,query(p<<1|1,mid+1,r,mid+1,qr,v));
		}
		if(qr<=mid)return query(p<<1,l,mid,ql,qr,v);
		if(ql>mid)return query(p<<1|1,mid+1,r,ql,qr,v);
		rmax=0;
		int tmp=query(p<<1|1,mid+1,r,mid+1,qr,v);
		return min(tmp,query(p<<1,l,mid,l,mid,rmax));
	}
	inline void insert(int p,int l,int r,int x,int v){
		if(l==r){
			t[p].f=f[v];t[p].mx=v;
			return;
		}int mid=(l+r)>>1;
		if(x<=mid)insert(p<<1,l,mid,x,v);
		else insert(p<<1|1,mid+1,r,x,v);
		t[p].mf=query(p<<1,l,mid,l,mid,t[p<<1|1].mx);
		t[p].f=min(t[p<<1].f,t[p<<1|1].f);
		t[p].mx=max(t[p<<1].mx,t[p<<1|1].mx);
	}
	inline short main(){
		n=read();
		F(i,1,n)p[i]=read();
		F(i,1,n)c[i]=read();
		F(i,1,n*4)t[i].f=t[i].mf=inf;
		for(register int i=1;i<=n*4;i<<=1)t[i].f=t[i].mf=0;
		F(i,1,n){
			f[i]=query(1,0,n,0,p[i]-1,0)+c[i];
			insert(1,0,n,p[i],i);
		}
		int T=0;
		D(i,n,1)if(p[i]>T)T=p[i],an=min(an,f[i]);
		pi(an);
		return 0;
	}
}
signed main(){return EMT::main();}
T3

倍增维护单调栈...(说是单调栈,其实栈数组都不用开

\(f_{i,j}\)表示在栈内i的j级父亲,不断弹栈、维护即可。

Code

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
namespace EMT{
	#define pf printf
	#define F(i,a,b) for(register int i=a;i<=b;i++)
	#define D(i,a,b) for(register int i=a;i>=b;i--)
	typedef double db;//(double)clock() / (double)CLOCKS_PER_SEC;
	inline int read(){int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();return x*f;}
	inline db min(db a,db b){return a<b?a:b;}inline db max(db a,db b){return a>b?a:b;}
	inline void pi(int x){pf("%d ",x);}inline void pn(){pf("\n");}
	inline void file(){freopen("in.in","r",stdin);freopen("my.out","w",stdout);}
	const int N=5e5+100;
	int deep[N],n,head[N],co,c[N],fa[N][22];db ans[N];
	struct node{int next,to;}e[N<<1];
	inline void add(int next,int to){e[++co].next=head[next],e[co].to=to,head[next]=co;}
	inline bool lop(int x,int y,int t){return (db)(c[x]-c[t])/(db)(deep[t]-deep[x])<(db)(c[y]-c[t])/(db)(deep[t]-deep[y]);}
	inline void dfs(int k,int f){
		deep[k]=deep[f]+1;
		D(i,20,0){
			if(fa[f][i]<=1)continue;
			int t=fa[f][i];
			if(lop(fa[t][0],t,k))f=t;
		}
		if(f>1){
			if(lop(fa[f][0],f,k))f=fa[f][0];
		}fa[k][0]=f;
		ans[k]=(db)(c[fa[k][0]]-c[k])/(db)(deep[k]-deep[fa[k][0]]);
		F(i,1,20)fa[k][i]=fa[fa[k][i-1]][i-1];
		for(register int i=head[k],j;i;i=e[i].next)j=e[i].to,dfs(j,k);
	}
	inline short main(){
		n=read();
		F(i,1,n)c[i]=read();
		F(i,2,n){int x=read();add(x,i);}
		dfs(1,0);
		F(i,2,n)pf("%.10lf",ans[i]),pn();
		return 0;
	}
}
signed main(){return EMT::main();}