edu111
A. Find The Array
题意
让我们称由
n
n
n正数(大于
0
0
0)组成的数组为
a
a
a如果对于从
1
1
1到
n
n
n的每个
i
i
i都满足以下条件,则整数很漂亮:
a
i
=
1
a_i=1
ai=1
,或者数组中至少存在数字
a
i
−
1
a_i−1
ai−1
和
a
i
−
2
a_i−2
ai−2中的一个。给定
s
s
s,求数组和为
s
s
s的漂亮数组的最小可能大小。
思路
为了满足和为 s s s的同时数组元素最小,那么我们选择每一个元素为其前一个+2是最优的,即构造一个奇数序列,直到其和大于等于 s s s。
代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
int s;cin>>s;
for(int i=1;i<=5010;i++)
{
if((1+2*i-1)*i/2>=s) {cout<<i<<endl;return;}
}
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)
solve();
return 0;
}
B. Maximum Cost Deletion
题意
您将得到一个长度为 n n n的字符串 s s s其中仅包含字符 0 0 0和 1 1 1。执行以下操作,直到字符串变为空:选择一些相等字符的连续子串,将其从字符串中擦除,并将剩余的两个部分粘合在一起(其中任何一个都可以是空的)按照同样的顺序。例如,如果从字符串 111110 111110 111110中擦除子串 111 111 111,则将得到字符串 110 110 110。删除长度为 l l l的子字符串时,将获得 a ⋅ l + b a⋅l+b a⋅l+b点。您的任务是,如果必须将给定的字符串设置为空,则计算您可以获得的最大总点数.
思路
可以发现只有两种策略
- 1 删的次数尽可能多,即 n n n个字符删 n n n次,那么贡献为 n ∗ ( a + b ) n*(a+b) n∗(a+b)
- 2 删的次数尽可能少,即尽可能地删连续的
0
0
0或
1
1
1,可以证明先删除完
0
0
0或
1
1
1地删除策略是删除次数最少的。计连续子串
0
0
0的个数为
c
n
t
0
cnt0
cnt0,连续子串
1
1
1的个数为
c
n
t
1
cnt1
cnt1,打表发现,如果
c
n
t
0
=
=
c
n
t
1
cnt0==cnt1
cnt0==cnt1,那么最少删除次数为
c
n
t
0
+
1
cnt0+1
cnt0+1,否则最少删除次数为
m
a
x
(
c
n
t
0
,
c
n
t
1
)
max(cnt0,cnt1)
max(cnt0,cnt1),计最少删除次数为
c
n
t
cnt
cnt,那么贡献为
n
∗
a
+
b
∗
c
n
t
n*a+b*cnt
n∗a+b∗cnt。
比较两种策略的贡献取最大值即可。
代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
int n,a,b;
cin>>n>>a>>b;
string s;cin>>s;
ll ans1,ans2;
ans1=ans2=0;
int cnt0,cnt1;
cnt0=cnt1=0;
for(int i=0;i<n;i++)
{
if(s[i]=='0')
{
int j=i;
while(j<n && s[j]=='0') j++;
cnt0++;
i=j-1;
}
}
for(int i=0;i<n;i++)
{
if(s[i]=='1')
{
int j=i;
while(j<n && s[j]=='1') j++;
cnt1++;
i=j-1;
}
}
//cout<<cnt0<<" "<<cnt1<<endl;
int cnt=0;
if(cnt0==cnt1) cnt=cnt0+1;
else cnt=max(cnt0,cnt1);
ans1=b*cnt+n*a;
ans2=n*(a+b);
cout<<max(ans1,ans2)<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)
solve();
return 0;
}
C. Manhattan Subarrays
疑似有点太猜了,(注意力低下导致的
题意
设有三个点
p
,
q
,
r
p,q,r
p,q,r,如果
d
(
p
,
r
)
=
d
(
q
,
p
)
+
d
(
q
,
r
)
d(p,r)=d(q,p)+d(q,r)
d(p,r)=d(q,p)+d(q,r),那么称其为一个坏的三元组,其中
d
(
x
,
y
)
d(x,y)
d(x,y)为x与y的欧几里得距离。
假设数组
b
1
,
b
2
,
…
,
b
m
b_1,b_2,…,b_m
b1,b2,…,bm是好的,如果不可能选择三个不同的索引
i
i
i
,
j
j
j,使得点
(
b
i
,
i
)
(b_i,i)
(bi,i)、
(
b
j
,
j
)
(b_j,j)
(bj,j)和
(
b
k
,
k
)
(b_k,k)
(bk,k)形成坏三元组。您将得到一个数组
a
1
,
a
2
,
…
,
a
n
a_1,a_2,…,a_n
a1,a2,…,an。计算
a
a
a的良好子数组的数量。数
a
a
a的子数组是某些
1
≤
l
≤
r
≤
n
1 \le l \le r \le n
1≤l≤r≤n的数组
a
l
,
a
l
+
1
,
…
,
a
r
a_l,a_{l+1},…,a_r
al,al+1,…,ar。注意,根据定义,长度为
1
1
1和
2
2
2的子数组是好的。
思路
- 1.首先对于三个下标,
i
<
j
<
k
i<j<k
i<j<k,只有满足
a
i
≤
a
j
≤
a
k
a_i \le a_j \le a_k
ai≤aj≤ak 或
a
i
≥
a
j
≥
a
k
a_i \ge a_j \ge a_k
ai≥aj≥ak 才可能是一个坏的三元组,证明如下
其中红色部分之和等于蓝色部分之和
-
2.没看明白的地方,只有长度 ≤ 4 \le 4 ≤4的子数组可能是漂亮的子数组
根据如上策略,长度为 1 和 2 1和2 1和2的子数组贡献为 n + n − 1 n+n-1 n+n−1,再枚举长度为 3 和 4 3和4 3和4的子数组是否满足条件1即可。
代码
#include<bits/stdc++.h>
#define ull unsigned long long
#define ll long long
#define inf 0x3f3f3f3f
#define lc p<<1
#define rc p<<1|1
#define endl '\n'
#define all(a) a.begin()+1,a.end()
#define all0(a) a.begin(),a.end()
#define lowbit(a) (a&-a)
#define fi first
#define se second
#define pb push_back
#define yes cout<<"YES"<<endl
#define no cout<<"NO"<<endl
using namespace std;
const double eps=1e-6;
typedef pair<int,int>PII;
typedef array<int,3>PIII;
mt19937_64 rnd(time(0));
void solve()
{
int n;cin>>n;
vector<int>f(n+1);
for(int i=1;i<=n;i++) cin>>f[i];
ll ans=n+n-1;
auto check=[&](int a,int b,int c)
{
return(f[a]<=f[b] && f[b]<=f[c]) || (f[a]>=f[b] && f[b]>=f[c]);
};
for(int i=1;i<=n-2;i++)
{
if(!check(i,i+1,i+2)) ans++;
}
for(int i=1;i<=n-3;i++)
{
if(!check(i,i+1,i+2) && !check(i,i+1,i+3) && !check(i,i+2,i+3) && !check(i+1,i+2,i+3)) ans++;
}
cout<<ans<<endl;
}
int main()
{
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int t;cin>>t;
while(t--)
solve();
return 0;
}