hgoi#20191115

muronglin
muronglin 2019年11月15日
  • 在其它设备中阅读本文章

T1- 表演

给你一幅既带点权又带边权的无向图 点权表示在这个点完成任务的花费 求从每个点出发到某一个点完成任务再回来的最小花费

解法

最短路模板, $dis$ 数组初始赋为点权,然后边权全部乘 $2$

ac 代码

#include<bits/stdc++.h>
#define pb push_back
#define ll long long 
using namespace std;
inline void readint(int&x)
{
    x=0;int fh=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')fh=-1;
    for(;isdigit(c);c=getchar())x=x*10+c-'0';
    x*=fh;
}
inline void readll(ll&x)
{
    x=0;ll fh=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')fh=-1;
    for(;isdigit(c);c=getchar())x=x*10+c-'0';
    x*=fh;
}
inline void print(ll x)
{
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
struct node
{
    int id;ll w;
    bool operator<(const node&a)const{return w>a.w;}
};
priority_queue<node>q;
vector<int>e[200010];
vector<ll>w[200010];
int n,m,x,y;
ll z,ans[200010];
bool vis[200010];
void solve()
{
    for(int i=1;i<=n;i++)
        q.push((node){i,ans[i]});
    while(!q.empty())
    {
        node u=q.top();q.pop();
        if(vis[u.id])continue;
        vis[u.id]=1;
        int sz=e[u.id].size();
        for(int i=0;i<sz;i++)
            if(anse[u.id]>ans[u.id]+wu.id)
                anse[u.id]=ans[u.id]+wu.id,
                q.push((node){eu.id,anse[u.id]});
    }
}
int main()
{
    freopen("exciting.in","r",stdin);
    freopen("exciting.out","w",stdout);
    readint(n),readint(m);
    for(int i=1;i<=m;i++)
        readint(x),readint(y),readll(z),z+=z,
        e[x].pb(y),w[x].pb(z),
        e[y].pb(x),w[y].pb(z);
    for(int i=1;i<=n;i++)
        readll(ans[i]);
    solve();
    for(int i=1;i<=n;i++)
        print(ans[i]),putchar(' ');
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T2- 逮虾户

你用 $t$ 的时间行了 $n$ 段路 现在给你每段路的路程以及估计速度 估计速度与真实速度的差值一定 求出这个差值

解法

这就是一个减函数,二分就好了。。。

ac 代码

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f 
#define eps (1e-9)
#define epss (1e-20)
using namespace std;
int n;
double t,minn,s[1010],v[1010];
double solve(double d)
{
    double tmp=0.0;
    for(int i=1;i<=n;i++)
        tmp+=s[i]/(v[i]+d);
    return tmp;
}
int main()
{
    freopen("dejavu.in","r",stdin);
    freopen("dejavu.out","w",stdout);
    scanf("%d%lf",&n,&t),minn=inf;
    for(int i=1;i<=n;i++)
        scanf("%lf%lf",&s[i],&v[i]),
        minn=fmin(minn,v[i]);
    double l=eps-minn,r=inf;
    while(r-l>=eps)
    {
        double mid=(l+r)/2.0,tmp=solve(mid);
        if(tmp>=t)l=mid;else r=mid;
    }
    printf("%.9lf",l);
    fclose(stdin);
    fclose(stdout);
    return 0;
}

T3- 跳一跳

给你一个数组 $A$ ,求它最长的满足奇数项小于两边的偶数项或偶数项小于两边的奇数项的子序列

解法

这就是个贪心,每次放进来一个数如果能增加长度就塞进去,不然就替换这个数

ac 代码

#include<bits/stdc++.h>
using namespace std;
inline void read(int&x)
{
    x=0;int fh=1;char c=getchar();
    for(;!isdigit(c);c=getchar())if(c=='-')fh=-1;
    for(;isdigit(c);c=getchar())x=x*10+c-'0';
    x*=fh;
}
inline void print(int x)
{
    if(x>9)print(x/10);
    putchar(x%10+'0');
}
int n,x,lst,opt1,opt2,ans1,ans2;
int main()
{
    freopen("jump.in","r",stdin);
    freopen("jump.out","w",stdout);
    read(n),read(lst),opt2=ans1=ans2=1;
    for(int i=2;i<=n;i++)
    {
        read(x);
        (x>lst)&&(ans1+=!opt1,ans2+=!opt2,opt1=opt2=1);
        (x<lst)&&(ans1+=opt1,ans2+=opt2,opt1=opt2=0);
        lst=x;
    }
    print(max(ans1,ans2));
    fclose(stdin);
    fclose(stdout);
    return 0;
}