时空警察狙击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;
}