noip模拟16
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();}
Everything that kills me makes me feel alive.