诣天诣练01

A. Serval and Bus

手速题,题意给你n个车次和到达时间,帮S同学坐上最早的车。车有第一次到达时间和间隔时间。

分析:很简单,只需让所有车次都变成达到时间之后的,然后挑选最早的那个即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;

int t, n, x[maxn];
struct nod
{
    int s, d, re;
} m[maxn];
bool cmp(nod x, nod y)
{
    return x.s < y.s;
}
int main()
{
    scanf("%d%d", &n, &t);
    int flag = 0;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d%d", &m[i].s, &m[i].d);
        m[i].re = i;
        while(m[i].s < t)
            m[i].s += m[i].d;
    }

    sort(m + 1, m + n + 1, cmp);
    printf("%d\n", m[1].re);
    return 0;
}

B - Serval and Toy Bricks CodeForces - 1153B

简单思维题,简单到没有思维含量,给你正面看的高度和侧面看的高度,然后让你给出柱体摆放的可能情况。

因为我们看到的只能是最高高度,因而可能情况可以简单的构造为正面和侧面看到的最小值。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 110;

int n, m, h, a[maxn], b[maxn], mp[maxn][maxn];
int main()
{
    scanf("%d%d%d", &n, &m, &h);
    for(int i = 1; i <= m; i++) scanf("%d", &a[i]);
    for(int i = 1; i <= n; i++) scanf("%d", &b[i]);
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j <= m; j++)
        {
            scanf("%d", &mp[i][j]);
            if(mp[i][j]) mp[i][j] = min(a[j], b[i]);
        }
    }
    for(int i = 1; i <= n; i++)
    {
        printf("%d", mp[i][1]);
        for(int j = 2; j <= m; j++)
        {
            printf(" %d", mp[i][j]);
        }
        printf("\n");
    }
    return 0;
}

C. Serval and Parenthesis Sequence

有点难度的字符串贪心题。读题难度++,跑偏++;

题意:让你把问号用‘(’或‘)’补全,而且要求不能有前缀括号。写出一个可能情况。

分析贪心我们可以尽可能把前面凑齐n/2 个‘(’然后剩下的补成‘)’最后看看是否合适即可。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;

int n;
char ch[maxn];
int main()
{
    scanf("%d", &n);
    scanf("%s", ch + 1);
    if(n % 2) printf(":(\n");
    else
    {
        int a = 0, flag = 0;
        for(int i = 1; i <= n; i++)
            if(ch[i] == '(') a++;
        for(int i = 1; i <= n; i++)
            if(ch[i] == '?' && a < n / 2) ch[i] = '(', a++;
        for(int i = 1; i <= n; i++)
            if(ch[i] == '?') ch[i] = ')';
        a = 0;
        for(int i = 1; i <= n; i++)
        {
            if(ch[i] == '(') a++;
            else
            {
                a--;
                if((a == 0 && i != n)|| a < 0) flag = 1;
            }
        }
        if(flag || a) printf(":(\n");
        else cout << ch + 1 << '\n';
    }

    return 0;
}

D. Serval and Rooted Tree(DP)

这个有难度了,嘤。

题意,给你一群数,然后他们都是有一个状态0/1,0说明它取最小的子树的值,1取最大的。非叶子节点的值由子节点决定,叶子结点的值从1 - n。

分析;由题意我们可以看出叶子结点的数目决定编号的大小,最大值则为cnt(叶子结点数)+ 1 - dp[1]。

状态转移方程

x == 0 dp[t] += dp[vec[t][i]]; // 0取最小,因而把所有子节点加起来

x == 1 dp[t] = min(dp[t], dp[vec[t][i]]); // 1取最大,只要有了最小值减去极为最大值

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 10;

vector <int> vec[maxn];
int n, a[maxn], dp[maxn], cnt, vis[maxn];
map <int, int> mp;
void dfs(int t)
{
    if(vec[t].size() == 0)
    {
        dp[t] = 1;
        return;
    }
    if(a[t] == 1)
    {
        dp[t] = 0x3f3f3f3f;
        for(int i = 0; i < vec[t].size(); i++)
        {
            dfs(vec[t][i]);
            dp[t] = min(dp[t], dp[vec[t][i]]); // == 1的情况
        }
    }
    else
    {
        for(int i = 0; i < vec[t].size(); i++)
        {
            dfs(vec[t][i]);
            dp[t] += dp[vec[t][i]]; 
        }
    }
    return ;
}
int main()
{
    scanf("%d", &n);
    cnt = n;
    for(int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i = 2; i <= n; i++)
    {
        int fa;
        scanf("%d", &fa);
        if(!vis[fa]) cnt--, vis[fa] = 1; // 统计叶子结点数目
        vec[fa].push_back(i);
    }
    dfs(1);
    printf("%d\n", cnt + 1 - dp[1]);
}

 

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值