2022.4.24
Educational Codeforces Round 127 (Rated for Div. 2)
A - String Building
a,b必须同时出现
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--)
{
string s="c";
cin >> s;
s += "c";
int cnt = 0, f = 0;
for (int i = 0; i < s.length();i++)
{
if(s[i]=='a'&&s[i-1]!='a'&&s[i+1]!='a')
{
f = 1;
break;
}
}
if(f)
{
cout << "no\n";
continue;
}
cnt = 0;
for (int i = 0; i < s.length();i++)
{
if(s[i]=='b'&&s[i-1]!='b'&&s[i+1]!='b')
{
f = 1;
break;
}
}
if(f)
{
cout << "no\n";
continue;
}
cout << "yes\n";
}
return 0;
}
B - Consecutive Points Segment
发现:最多只能有一次间隔为3,且其他间隔必须为1,否则失败,如:1 3 6则失败,2 3 6成功,最多只能有两次间隔为2,且不能有间隔为3,如:1 3 5 7,则失败,2 3 5 7成功。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+10,INF=1e9;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--)
{
int n;
cin >> n;
for (int i = 1; i <= n;i++)
{
cin >> a[i];
}
int f = 0,cnt1=0,cnt2=0;
for (int i = 2; i <= n;i++)
{
if(a[i]-a[i-1]>3)
{
f = 1;
break;
}
else if(a[i]-a[i-1]==3)
{
cnt1++;
if(cnt1>1||cnt2)
{
f = 1;
break;
}
}
else if(a[i]-a[i-1]==2)
{
cnt2++;
if(cnt2>2||cnt1)
{
f = 1;
break;
}
}
}
if (f)
cout << "NO\n";
else
cout << "YES\n";
}
return 0;
}
C-Dolce Vita
考虑贪心,每次都先买价格最低的,于是按价格从小到大排序,如果枚举天数则会超时,如果枚举买1-n的糖果最多能买多少个则转化为求买1-n种糖果的前缀和,如果买一种,则之后的天数每天价格会加1,买2种则价格每天加2,n种每天加n。因此从1-n枚举买i种糖果的天数再求和。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=2e5+10,INF=1e9;
ll a[N],sum[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin >> t;
while(t--)
{
ll n, x;
cin >> n >> x;
for (int i = 1; i <= n;i++)
{
cin >> a[i];
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n;i++)
{
sum[i] = sum[i - 1] + a[i];
}
ll ans = 0;
for (int i = 1; i <= n;i++)
{
if(sum[i]>x)//超过了就不能买
continue;
ll cnt = (x - sum[i]) / i + 1;//后面还能再买几次
ans += cnt;
}
cout << ans<<'\n';
}
return 0;
}
Codeforces Round #748 (Div. 3)
A - Elections
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int a,b,c;
cin >> a >> b >> c;
if(a<=max(b,c))
cout << max(b, c) + 1 - a<<' ';
else
cout << 0 << ' ';
if(b<=max(a,c))
cout << max(a, c) + 1 - b<<' ';
else
cout << 0 << ' ';
if(c<=max(b,a))
cout << max(b, a) + 1 - c<<'\n';
else
cout << 0 << '\n';
}
return 0;
}
B - Make it Divisible by 25
当在百位以上的时候00可以整除25,在十位时,25,50,75,可以整除25,于是我们只需要删除他们之间的数以及在他们后面的数就可以满足要求。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<string>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
const string ss[] = {"00", "25", "50", "75"};
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
string s;
cin>>s;
int ans = INF;
for (int i = 0; i < 4;i++)
{
int x = s.length() - 1;
int res = 0;
while(x>=0&&s[x]!=ss[i][1])
{
x--;
res++;
}
if(x<0)
continue;
x--;
while(x>=0&&s[x]!=ss[i][0])
{
x--;
res++;
}
if(x<0)
continue;
ans = min(res, ans);
}
cout << ans << '\n';
}
return 0;
}
C - Save More Mice
为了救更多的老鼠,考虑贪心先救离洞口最近的老鼠,猫会在第n秒到达洞口,如果当前的时间加上转移老鼠到洞口的时间小于n的话就可以救,同时更新时间,否则救不了。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4e5+10,INF=1e9;
int a[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int n, m;
cin >> n >> m;
for (int i = 1; i <= m;i++)
{
cin>>a[i];
a[i] = n - a[i];
}
sort(a + 1, a + 1 + m);
ll now = 0,cnt = 0;
for (int i = 1; i <= m;i++)
{
if(now+a[i]<n)
{
now += a[i];
cnt++;
}
else
break;
}
cout << cnt << '\n';
}
return 0;
}
D1 - All are Same
就是最大公约数,例如 1 5 3 ,1-5 需要加4,3-5需要加2,那么加4可以用两次加2代替。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=1e5+10,INF=1e9;
ll a[50];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int n;
cin>>n;
int f = 0;
map<int, int> mp;
for (int i = 1; i <= n;i++)
{
cin >> a[i];
mp[a[i]]++;
if(mp[a[i]]==n)
{
f = 1;
}
}
if(f)
{
cout << "-1\n";
continue;
}
ll ans = abs(a[2] - a[1]);
for (int i = 3; i <= n;i++)
{
ans = __gcd(ans, abs(a[i] - a[i - 1]));
}
cout << ans << '\n';
}
return 0;
}
E - Gardener and Tree
一开始暴力模拟删边操作,但是超时。考虑把每个结点的度记下来.如果结点的度为1说明是叶子,需要删除,有点类似拓扑排序的操作,先把所有叶子都加入,然后删去和他们相连的边,如果相连的点的度减为了1,则该点变成了新的叶子继续加入队列,直到k次操作完或者没有节点可以删为止,特判当n=1时为0.
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<vector>
#include<queue>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N=4e5+10,INF=1e9;
vector<int> p[N];
int du[N];
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
int t;
cin>>t;
while(t--)
{
int n, k;
cin >> n >> k;
for (int i = 1; i <=n;i++)
{
p[i].clear();
du[i] = 0;
}
if(n==1)
{
cout << "0\n";
continue;
}
int cnt = n;
for (int i = 1; i < n;i++)
{
int a, b;
cin >> a >> b;
p[a].push_back(b);
p[b].push_back(a);
du[a]++;
du[b]++;
}
queue<pii> que;
for (int i = 1; i <= n;i++)
{
if(du[i]==1)
{
cnt--;
que.push({i, 1});
}
}
while(!que.empty())
{
pii t = que.front();
que.pop();
int x = t.first,now=t.second;
if(now==k||cnt==0)
break;
for (int i = 0, j = p[x].size(); i < j; i++)
{
int y = p[x][i];
du[y]--;
if(du[y]==1)
{
cnt--;
que.push({y, now + 1});
}
}
}
cout << cnt << '\n';
}
return 0;
}