Educational Codeforces Round 142

A-D

A. GamingForces

一眼题,当有两个怪兽的生命都为1时,使用操作1最优,否则,使用操作2

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,a[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n;
        map<int,int>mp;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
            mp[a[i]]++;
        }
        cout<<mp[1]/2+n-mp[1]/2*2<<"\n";

    }
    return 0;
}

B. Stand-up Comedian

若a1为0,则特判答案为1,否则先讲a1个笑话,然后再轮流依次讲a2,a3的笑话,直到a2,a3有笑话被讲完,此时两个观众的兴奋值仍为a1,再讨论讲剩下的笑话和兴奋值。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,a1,a2,a3,a4;
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>a1>>a2>>a3>>a4;
        if(a1==0)
        {
            cout<<1<<"\n";
            continue;
        }
        cout<<a1+min(a2,a3)*2+min(a1+1,a2+a3-min(a2,a3)*2+a4)<<"\n";
    }
    return 0;
}

C. Min Max Sort

序列操作为在全排序序列中取两个数,然后较小者放前面,较大者放最后。

求最小排序序列的次数,观察到,连续上升的序列是不用进行此操作来排序的,

则dp寻找以x结尾连续上升序列的个数,答案ans=max(x-dp[x],n-x),

对每个dp[x]进行更新答案,找到最小的ans。

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6;
int n,p[N],dp[N];
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n;
        int ans=1e8;
        for(int i=1;i<=n;i++)dp[i]=0;
        for(int i=1;i<=n;i++)
        {
            cin>>p[i];
            dp[p[i]]=dp[p[i]-1]+1;
            ans=min(ans,max(p[i]-dp[p[i]],n-p[i]));
        }
        cout<<ans<<"\n";
    }
    return 0;
}

D. Fixed Prefix Permutations

给出n个长度为m的全排序序列,定义排序p*q为创建一个新排序r

r[i]=q[p[i]]。对于一个序列x来说,beauty值为x[i]=i,连续成立的最大i值。

求每个序列对其他所有序列的p*q的beauty最大值。

使用字典树,对每个序列p来说,有一个最优的序列q,即满足q[p[i]]=i,

将此最优序列q挂上字典树,序列q的q[i]也代表着序列p的大小为i的值

在p序列的第q[i]个位置。

接下来,对每个原排序序列求p*q的beauty最大值,即将原排序序列放在

字典树上求最长前缀,为满足式子r[i]=q[p[i]]=i,依次来看,当i为1时,

即寻找q[p[1]]=1的串是否存在,即在字典树上检查是否存在序列q

有一个大小为p[1]的值在q序列的第1个位置上。

(有点绕,请结合代码打印出最优序列q仔细推敲,

直接在字典树挂原串用最优串来匹配是错误的因为q[p[i]]=i的p[i]不是按顺序的,

有可能跳着,但是原串的第i个又不满足q[p[i]]=i就会出错)

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+10;
int n,m,b[20],p[N][15];
struct tire
{
    int son[N][26],idx=0;
    void insert(int a[])
    {
        int p=0;
        for(int i=1; i<=m; i++)
        {
            int u=a[i];
            if(!son[p][u])son[p][u]=++idx;
            p=son[p][u];
        }
    }
    int query(int a[])
    {
        int p=0,ans=0;
        for(int i=1; i<=m; i++)
        {
            int u=a[i];
            if(!son[p][u])return ans;
            ans++;
            p=son[p][u];
        }
        return ans;
    }
};
signed main()
{
    ios::sync_with_stdio(false);
    cin.tie(0),cout.tie(0);
    int T=1;
    cin>>T;
    while(T--)
    {
        cin>>n>>m;
        tire t;
        for(int i=0;i<=n*10;i++)
        {
            for(int j=0;j<=10;j++)
                t.son[i][j]=p[i][j]=0;(结构体变量记得初始化)
        }
        for(int i=1; i<=n; i++)
        {
            for(int j=1; j<=m; j++)
            {
                cin>>p[i][j];
                b[p[i][j]]=j;
            }
            t.insert(b);
        }
        for(int i=1; i<=n; i++)
        {
            cout<<t.query(p[i])<<" ";
        }
        cout<<"\n";
    }
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值