• Codeforces 1099


    链接:https://codeforces.com/contest/1099


    A - Snowball - [模拟水题]

    题意:有一个雪球从山顶滚落,山坡上有两块石头,每秒钟会一次发生三件事:1、雪球增重,数值为当前高度;2、如果当前高度有一块石头,则会撞到石头,损失跟石头同样重的重量;3、往下移动一米。此外,若雪球的重量如果变为负数,则自动变成零。雪球会在高度为零处停止滚动,问停止滚动时雪球重量。

    题解:模拟水题。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int w,h;
    int u[2],d[2];
    int main()
    {
        cin>>w>>h;
        cin>>u[0]>>d[0]>>u[1]>>d[1];
        while(h)
        {
            w+=h;
            for(int i=0;i<=1;i++) if(h==d[i]) w-=u[i], w=max(w,0);
            h--;
        }
        cout<<w<<endl;
    }

    B - Squares and Segments - [简单数学题]

    题意:在一个无限大的网格上画正方形,只能画单位 $1$ 长度的线段,且端点只能在整数格点上。你如果想画 $(x,y)$ 到 $(x,y+1)$ 这样一条线段,如果存在 $(x',y)$ 到 $(x',y+1)$ 的另外一条线段,则可以直接画,否则就需要用尺子。对于 $(x,y)$ 到 $(x+1,y)$ 这样的线段也是类似的。求最少用几次尺子能画出 $n$ 个正方形。

    题解:显然,若 $n=k^2$,则 $ans=2 cdot k$。否则的话,找到满足 $(k-1)^2 < n < k^2$ 的 $k$,而 $ans$ 为 $2 cdot k$ 或者 $2 cdot k - 1$。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    const int eps=1e-10;
    int n;
    int main()
    {
        while(cin>>n)
        {
            int k=ceil(sqrt(n)-eps)+eps;
            if(k*k==n) cout<<2*k<<endl;
            else
            {
                int t=n-(k-1)*(k-1);
                cout<<((t>=k)?(2*k):(2*k-1))<<endl;
            }
        }
    }

    C - Postcard - [简单的字符串构造题]

    题意:给出一个小写字母组成的字符串,另外还包含“?”、“*”两个字符,“?”代表其前面的那个字母可以去掉或者留下,“*”代表其前面的那个字母可以重复零到任意多次。要求你给出一个长度为 $k$ 的操作后字符串。

    题解:首先“Impossible”的原因有两种,一种是长度过长,另一种是长度过短,先把这两种判掉。

    其次看看有没有“*”,如果没有,把一部分“?”前的字母留下来达到长度 $k$ 即可;如果有,那么别的全部扔掉,只用其中一个“*”重复字母,知道长度为 $k$。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    int k;
    string s;
    int main()
    {
        cin>>s>>k;
    
        int c1=0, c2=0;
        for(int i=0;i<s.size();i++)
        {
            if(s[i]=='?') c1++;
            if(s[i]=='*') c2++;
        }
        if(s.size()-2*(c1+c2)>k) //长度过长
        {
            printf("Impossible
    ");
            return 0;
        }
        if(c2==0 && s.size()-c1<k) //长度过短
        {
            printf("Impossible
    ");
            return 0;
        }
    
        int need=k-(s.size()-2*(c1+c2)); //cout<<need<<endl;
        if(c2>0)
        {
            for(int i=0;i<s.size();i++)
            {
                if(i+1<s.size() && s[i+1]=='?') {i++; continue;}
                if(i+1<s.size() && s[i+1]=='*')
                {
                    for(int t=1;t<=need;t++) printf("%c",s[i]);
                    need=0;
                    i++; continue;
                }
                printf("%c",s[i]);
            }
            printf("
    ");
        }
        else
        {
            for(int i=0;i<s.size();i++)
            {
                if(i+1<s.size() && s[i+1]=='?')
                {
                    if(need){printf("%c",s[i]); need--; i++; continue;}
                    else {i++; continue;}
                }
                printf("%c",s[i]);
            }
            printf("
    ");
        }
    }

    D - Sum in the tree - [DFS]

    题意:给出一棵有根树,根节点编号为 $1$,每个节点存在一个权值 $a[x]$,同时还有一个 $s[x]$ 为从根节点到节点 $x$ 这条路径上的所有节点的 $a[x]$ 之和。此时,擦除了所有深度为偶数的节点的 $s[x]$(根节点深度为 $1$)。然后要求反推出所有节点的 $a[x]$,使得所有节点的 $a[x]$ 之和最小。

    题解:很容易就能想到,对于一个 $s[x] = -1$ 节点,它的 $a[x]$ 的取值是受制于它的所有直系子节点的。而且,它的儿子节点们的 $s[y]$ 都是确保已知的,因此只存在两种情况:有儿子节点,$s[x]$ 取值就是 $min_{所有的edge(x,y)}(s[y])$,进而 $a[x] = s[x] - s[par(x)]$;如果没有儿子节点,那么显然取 $a[x] = 0$ 是最好的。然后根据这种思想,用DFS遍历一下树,算出每个节点的 $a[x]$ 就行了。

    AC代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int INF=0x3f3f3f3f;
    const int maxn=1e5+10;
    int n,a[maxn],s[maxn];
    vector<int> e[maxn];
    bool ok;
    void dfs(int now,int par,int d)
    {
        if(!ok) return;
        if(d%2==0)
        {
            if(e[now].empty()) s[now]=s[par], a[now]=0;
            else
            {
                int mn=INF;
                for(auto nxt:e[now]) mn=min(mn,s[nxt]);
                if(mn<s[par]) {ok=0; return;}
                else s[now]=mn, a[now]=s[now]-s[par];
            }
        }
        else a[now]=s[now]-s[par];
        for(auto nxt:e[now]) dfs(nxt,now,d+1);
    }
    int main()
    {
        cin>>n;
        for(int v=2,u;v<=n;v++) scanf("%d",&u), e[u].push_back(v);
        for(int i=1;i<=n;i++) scanf("%d",&s[i]);
    
        ok=1, s[0]=0;
        dfs(1,0,1);
    
        if(!ok) cout<<-1<<endl;
        else
        {
            ll ans=0;
            for(int i=1;i<=n;i++) ans+=a[i];
            cout<<ans<<endl;
        }
    }

    E - Nice table

     


    F - Cookies - [DFS+博弈+线段树]

  • 相关阅读:
    JS小功能系列9商品筛选
    JS小功能系列8省市联动
    if u
    js属性
    js初识
    弹性盒
    项目合作
    css重置
    关于响应式布局
    自我定位
  • 原文地址:https://www.cnblogs.com/dilthey/p/10259617.html
Copyright © 2020-2023  润新知