noip模拟16

cao  这场又挂掉分了,t1求距离打的int直接爆0了。。。。。

T1star way to heaven

怎么说呢,这个题要是看出来了,写个最小生成树的板子就过了,要是看不出来。。。。

我们把这个题目转化一下,说要经过的路径距离星星或边界的距离的最小值最大,

那么我们经过星星与星星或边界的终点肯定是不劣的,那么问题就转化成从左边到右边经过的所有连线的最小距离的1/2最大

我们发现,假设我们把上边界和下边界看作两个点,每个星星都和其他星星以及上下边界有连边,也就是说将他看作一张完全图

从上边界到下边界,有无数条路径,但是只要是从左边到右边经过,那么每一条路径我们都有一条边要经过,那么我们只要保证我们走的边是

这条路径上的最大值就可以保证是最优解,

而这里面的最小值就是最小生成树产生的从上边界到下边界的最大值,所以直接跑个最小生成树就行了

这题有点像直接写过的一个water,可以直接跑生成树找下最大值过掉。。。

 

noip模拟16
#include<bits/stdc++.h>
#define jb cout<<"jb";
using namespace std;
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<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
#define min(a,b) ((a)<(b)?(a):(b))    
#define max(a,b) ((a)<(b)?(b):(a))
const double esp=1e-9;
const int maxn=6e5+2;
int n,m,k;
double x[maxn],y[maxn];
int v[maxn],v2[maxn];
bool vis[maxn];
double dis[maxn];
inline double ds(double x1,double y1,double x2,double y2)
{
    return sqrt((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}
int main()
{
    n=read(),m=read();k=read();
    for(int i=1;i<=k;i++)
    x[i]=read(),y[i]=read();
    for(int i=1;i<=k;i++)
    dis[i]=m-y[i];
    dis[k+1]=m; dis[0]=1e9;
    double ans;
    while(1)
    {
        int mi=0;
        for(int i=1;i<=k+1;i++)
        {
            if(!vis[i]&&dis[i]<dis[mi])
             mi=i;
        }
        ans=max(ans,dis[mi]);
        vis[mi]=1;
        if(mi==k+1)
        {
            printf("%.8lf",ans/2.0);
            return 0;
        }
        for(int i=1;i<=k;i++)
        {
            dis[i]=min(dis[i],ds(x[i],y[i],x[mi],y[mi]));
        }
        dis[k+1]=min(dis[k+1],y[mi]);
    }
}
T1

T2God Knows

很难,又是数据结构题

线段树维护单调栈,建议看天皇skyh的博客,这里就只有个代码了

 

noip模拟16
#include<bits/stdc++.h>
#define lid id<<1
#define rid id<<1|1
using namespace std;
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<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
const int maxn=2e6+1;
const int inf=2e9;
int c[maxn],p[maxn],f[maxn],n;
inline int max(int x,int y){return x<y?y:x;}
inline int min(int x,int y){return y<x?y:x;}
struct segtree{
    int l,r,mn,mx,un;
}tr[maxn<<2];
inline int calc(int id,int nxt)
{
    if(tr[id].l==tr[id].r) 
    return tr[id].mx>nxt?tr[id].mn:inf;
    if(tr[rid].mx>nxt) return min(tr[lid].un,calc(rid,nxt));
    return calc(lid,nxt);
}
void pushup(int id)
{
    tr[id].mx=max(tr[lid].mx,tr[rid].mx);
    tr[id].mn=min(tr[rid].mn,tr[lid].un=calc(lid,tr[rid].mx));
}
void build(int id,int l,int r)
{
    tr[id].l=l,tr[id].r=r;
    tr[id].mn=tr[id].un=inf;
    tr[id].mx=-1;
    if(l==r) return ;
    int mid=(l+r)>>1;
    build(lid,l,mid);
    build(rid,mid+1,r);
}
int nxt;
inline int query(int id,int l,int r)
{    
    if(tr[id].l>=l&&tr[id].r<=r)
    {
        int ans=calc(id,nxt);
        nxt=max(tr[id].mx,nxt);
        return ans;
    }
    int ans=inf;
    if(r>=tr[rid].l) ans=min(ans,query(rid,l,r));
    if(l<=tr[lid].r) ans=min(ans,query(lid,l,r));
    return ans;
}
inline void update(int id,int pos,int i,int val)
{
    if(tr[id].l==tr[id].r)
    {
        tr[id].mn=val;
        tr[id].mx=i;
        return ;
    }
    if(pos<=tr[lid].r) update(lid,pos,i,val);
    if(pos>=tr[rid].l) update(rid,pos,i,val);
    pushup(id);
}
int main()
{
    //freopen("a.in","r",stdin);
    n=read();
    for(int i=1;i<=n;++i) p[i]=read();
    for(int i=1;i<=n;++i) c[i]=read();
    n++;
    p[n]=n;
    build(1,1,n);
    update(1,1,0,0);
    for(int i=1,k;i<=n;i++)
    {
        nxt=-1;
        k=query(1,0,p[i]-1)+c[i];
        update(1,p[i],i,k);
        if(i==n)
        printf("%d\n",k);
    }    
}
T2

 

T3Lost  may  music

这第一眼就是个斜率,可是没有学过,

求值公式其实就是斜率的复制

大体上就是维护一个突包,用倍增来维护单调栈,代码挺好写的

noip模拟16
#include<bits/stdc++.h>
using namespace std;
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<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}
const int maxn=5e5+5;
int fa[maxn][21];
int n,c[maxn],dep[maxn];
int head[maxn],to[maxn*2],nxt[maxn*2],num;
int ans[maxn];
double calc(int x,int y){return 1.0*(c[y]-c[x])/(dep[y]-dep[x]);}
inline void add(int x,int y){to[++num]=y,nxt[num]=head[x];head[x]=num;}
void dfs(int x)
{
    int father=fa[x][0];
    for(int i=19;i>=0;i--)
    {
        if(fa[father][i]<=1) continue;
        if(calc(x,fa[father][i])<=calc(x,fa[fa[father][i]][0]))
        father=fa[father][i];
    }
    if(calc(x,father)<=calc(x,fa[father][0])&&father>1) father=fa[father][0];
    ans[x]=fa[x][0]=father;
    for(int i=1;i<=19;i++)
    fa[x][i]=fa[fa[x][i-1]][i-1];
    for(int i=head[x];i;i=nxt[i])
    {
        int y=to[i];
        dep[y]=dep[x]+1;
        dfs(y);
    }
}
int main()
{
    n=read();
    for(int i=1;i<=n;i++)    
    {
        c[i]=read();    
    }
    for(int i=2;i<=n;i++)
    {
        fa[i][0]=read();
        add(fa[i][0],i);
    }
    dfs(1);
    for(int i=2;i<=n;i++)
    {
        printf("%.8lf\n",-calc(i,ans[i]));
    }
}
T3

 

上一篇:hicp 第三天作业


下一篇:[C#] 代码混淆和加壳