Codeforces Round #374 (Div. 2)

A. One-dimensional Japanese Crossword

顺序扫一遍,记录一蛤连续的 'B' 序列就好。

$O(n)$

 1 #include<iostream>
 2 #include<cstdio>
 3 using namespace std;
 4 
 5 int n;
 6 char a[1000];
 7 int ans[1000];
 8 int cnt = 0;
 9 int main()
10 {
11     scanf("%d",&n);
12     scanf("%s",&a);
13     for (int i = 0; i < n; i++)
14     {
15         if (a[i] == 'B') ans[cnt]++;
16         else if (ans[cnt] != 0 && a[i] == 'W') cnt++;
17 
18         if (ans[cnt] != 0 && i == n-1) cnt++;
19     }
20     printf("%d\n",cnt);
21     for (int i = 0; i < cnt; i++)
22         printf("%d ",ans[i]);
23     printf("\n");
24 }
View Code

 

B. Passwords

记录每个长度的串的个数,分别讨论一下最优和最差就好了。

$O(n)$

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<string>
 4 using namespace std;
 5 
 6 string str;
 7 int len[1000];
 8 int n,k;
 9 int c;
10 int total = 0;
11 int main()
12 {
13     scanf("%d %d",&n,&k);
14     for (int i = 0; i < n; i++)
15     {
16         cin>>str;
17         len[str.length()] ++;
18     }
19     cin>>str;
20     c = str.length();
21     for (int i = 0; i < c; i++)
22         total += len[i];
23 
24     int mini = total + 1;
25     int maxi = total + len[c];
26     printf("%d %d",mini + (mini - 1)/k*5, maxi + (maxi - 1)/k*5);
27 }
View Code

 

C. Journey

求权值之和不超过T的从1到n的最长路径。由于是拓扑图,BFS+记忆化搜索就可做。记录一下更新的情况还原路径。

$ dp[i][j] = $到第i个点时已经路径长为j时的路径最小花费。

bfs中queue可以改为priority_queue优化

$O((n+m)*m) $

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<vector>
 4 #include<cstring>
 5 #include<queue>
 6 #include<stack>
 7 using namespace std;
 8 
 9 struct edge{
10     int to, cost;
11 };
12 
13 struct node{
14     int p, left, num, _prev;
15 };
16 int n,m,T;
17 vector<edge> G[5010];
18 
19 int dp[5010][5010]; // 第n个点,已经经过多少个点,所剩余最多的钱
20 int _prev[5010][5010]; //第n个点 已经经过多少个点,前趋
21 
22 void solve()
23 {
24     queue<node> que;
25     que.push(node{1,T,1,0});
26     while(!que.empty())
27     {
28         node no = que.front();
29         que.pop();
30         if (dp[no.p][no.num] >= no.left) continue;
31         else
32         {
33             dp[no.p][no.num] = no.left;
34             _prev[no.p][no.num] = no._prev;
35 
36             for (int i = 0; i < G[no.p].size(); i++)
37             {
38                 edge e = G[no.p][i];
39                 if (no.left - e.cost < 0 || dp[e.to][no.num + 1] >= no.left - e.cost) {
40                 }
41                 else
42                 {
43                     que.push(node{e.to, no.left - e.cost, no.num + 1, no.p});
44                 }
45             }
46         }
47     }
48     int ans = 0;
49     for (int i = n; i >= 1; i--)
50     {
51         if (dp[n][i] != -1) {ans = i; break;}
52     }
53     stack<int> path;
54     path.push(n);
55     int cnt = ans;
56     while(path.top()!= 1 &&cnt >= 0)
57     {
58         path.push(_prev[path.top()][cnt--]);
59     }
60     printf("%d\n",ans);
61     while(!path.empty())
62     {
63         printf("%d ",path.top());
64         path.pop();
65     }
66     printf("\n");
67 
68 }
69 int main()
70 {
71     scanf("%d %d %d",&n,&m,&T);
72     for (int i = 0; i < m; i++)
73     {
74         edge e;
75         int from;
76         scanf("%d %d %d",&from,&e.to,&e.cost);
77         G[from].push_back(e);
78     }
79 
80     memset(dp,-1,sizeof dp);
81     solve();
82 }
View Code

 

D. Maxim and Array

贪心。

使所有元素的乘积最小,首先需要尽可能使其为负数(注意多0的情况)。

利用优先队列维护一下当前所有元素的最小值就好了。

/*

  公式推导留坑。

*/

$ O((n+k)logn) $

#include<iostream>
#include<cstdio>
#include<queue>
#include<utility>
using namespace std;

typedef long long ll;
typedef pair<ll,ll> P;
ll a[200000];
ll n,k,x;
ll _abs(ll x)
{
    if (x < 0) return -x;
    return x;
}

int sign = 1;
 int main()
{
    priority_queue<P, vector<P>, greater<P> > que;
    scanf("%I64d %I64d %I64d",&n,&k,&x);
    for (int i = 0; i < n;  i++)
    {
        scanf("%I64d",&a[i]);
        if (a[i] < 0) {
            sign = -sign;
        }
        que.push(P(_abs(a[i]),i));
    }
    if (n > 0)
    while( k > 0)
    {

        ll pos = que.top().second;
        ll val = que.top().first;
        que.pop();
        ll times = 0;
        if (sign == 1)
        {
            times = val/x + 1;

            times = min(times,k);

            if (a[pos] > 0) a[pos] -= times*x;
            else if (a[pos] == 0) a[pos] -= times*x;
            else a[pos] += times*x;

            sign = -sign;
            k -= times;
            val = _abs(a[pos]);
            que.push(P(val,pos));
            continue;
        }

        ll aim = que.top().first;

        times = (aim - val)/x + 1;
        times = min(times,k);
        k -= times;
        if (a[pos] >= 0) a[pos] += times * x;
        else a[pos] -= times * x;
        val = _abs(a[pos]);
        que.push(P(val,pos));

    }
    else
        a[0] -= k*x;

    for (int i = 0; i < n; i++)
        printf("%I64d ",a[i]);
    printf("\n");

}
View Code

 

E. Road to Home

留坑

转载于:https://www.cnblogs.com/zjc-Connor/articles/5943029.html

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值