Bootstrap

Educational Codeforces Round 145 (Rated for Div. 2) A-D

时空警察狙击evilboy计划继续
本期封面原图 画师逢編いあむ

Educational Codeforces Round 145 (Rated for Div. 2)

A. Garland

题意

四盏灯,每次操作可以关或者开一盏灯,不能连续两次操作同色的灯,问打开所有灯的最小操作次数

思路

简单捋一下其实只有同色灯数最多的颜色会对答案造成影响,捋一下然后判断就行了

代码

#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;

void solve()
{
    string s;
    cin>>s;
    int st[10];
    memset(st,0,sizeof(st));
    int m=0;
    for(int i=0;i<s.size();i++)
    {
        st[s[i]-'0']++;
        m=max(m,st[s[i]-'0']);
    }
    if(m==4)
    {
        printf("-1\n");
    }
    else if(m==3)
    {
        printf("6\n");
    }
    else
    {
        printf("4\n");
    }
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

B. Points on Plane

题意

给你一个二维平面,你需要在其上放置 n n n 个棋子。
你只能将棋子放在整数坐标的点上。将棋子放在坐标点 ( x , y ) (x, y) (x,y) 上的成本等于 ∣ x ∣ + ∣ y ∣ |x| + |y| x+y (其中, ∣ a ∣ |a| a 表示 a a a 的绝对值)。
放置 n n n 个棋子的成本等于其中最大的单个棋子的成本。
你需要在平面上布置 n n n 个棋子,使得每对棋子之间的欧几里得距离严格大于 1 1 1 ,且成本尽可能小。

思路

很容易想到最好的方式其实是正方形一圈一圈围出去,因为同一圈的 ∣ x ∣ + ∣ y ∣ |x| + |y| x+y是相等的,一开始的想法是二分找圈数,然后答案就在下一圈,但我发现中间计算会爆long long。那我们再想一下,每一圈其实都是一个正方形,所以只需要把n所在的圈数补成比他大的第一个完全平方数,他所在的就是这一层嘛

代码

#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
//1,4,12,20,28

void solve()
{
    ll n;
    scanf("%lld",&n);
    ll s=sqrtl(n);
    if(s*s==n)
    {
        printf("%lld\n",s-1);
        return;
    }
    printf("%lld\n",s);
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

C. Sum on Subarrays

题意

给定n和k,构造一个长度为n的数组,要求恰好有k个连续子序列的和为正数,且剩下的都是负数

思路

先找恰好的,也就是先连续放正数,最后如果再放会导致子序列个数比k大了我们再处理零头,用一个恰好的数字使得只有从第1~零头个数开头到这个数的序列之和是正数就行了,这也是 O ( 1 ) O(1) O(1)就能算出来

代码

#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
// 1 2 3 4 5 6 7 8 9
// 1 3 6 10 15 21 28 36 45

void solve()
{
    int n,k;
    scanf("%d%d",&n,&k);
    vector<int> ans;
    for(int i=1;i<=n;i++)
    {
        if(k>=i)
        {
            ans.push_back(2);
            k-=i;
        }
        else if(k!=0)
        {
            ans.push_back(-2*(i-k)+1);
            k=0;
        }
        else
        {
            ans.push_back(-1000);
        }
    }
    for(auto x:ans)
        printf("%d ",x);
    printf("\n");
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}

D. Binary String Sorting

题意

给你一个01串,要求把他变成非递减的,交换相邻的两个数的代价是 1 0 12 10^{12} 1012,删除一个数的代价是 1 0 12 + 1 10^{12}+1 1012+1,最小化代价

思路

首先我们看到代价都很高,所以如果一下好几个1要移动肯定不可能一个一个换过去,一定是删掉中间的所有0更优,所以我想法是从后往前贪心,发现样例1过不了,遂dp,具体的转移方程和数组定义都在代码里了

代码

#include <bits/stdc++.h>
#define maxOf(a) *max_element(a.begin(),a.end())
#define minOf(a) *min_element(a.begin(),a.end())
#define all(a) a.begin(),a.end()
using namespace std;
typedef long long ll;
typedef double db;
typedef pair<int,int> pii;
typedef pair<ll,ll> pll;
const int N=3e5+5;
const ll swa=1e12,del=1e12+1;

void solve()
{
    string s;
    cin>>s;
    int n=s.size();
    vector<vector<ll>> dp(n+1,vector<ll>(3,0));
    //第一维表示当前位置,第二维0,1,2分别表示当前结尾为0,末尾有一个1,末尾有多个1
    for(int i=1;i<=n;i++)
    {
        int now=s[i-1]-'0';
        if(now)
        {
            dp[i][0]=dp[i-1][0]+del;
            dp[i][1]=dp[i-1][0];
            dp[i][2]=min(dp[i-1][1],dp[i-1][2]);
        }
        else
        {
            dp[i][0]=dp[i-1][0];
            dp[i][1]=dp[i-1][1]+swa;
            dp[i][2]=dp[i-1][2]+del;
        }
    }
    printf("%lld\n",min(dp[n][0],min(dp[n][1],dp[n][2])));
}

int main()
{
    int T=1;
    scanf("%d",&T);
    while(T--)
    {
        solve();
    }
    return 0;
}
;