标签:can sharp red puts ble bre pac 最小 多少
找两个奇数就行了。
#include<bits/stdc++.h>
using namespace std;
void solve()
{
int n; string s;
cin >> n >> s;
string ans = "";
for(int i = 0; i < n; i++)
{
if(int(s[i] - '0')%2 == 1)
ans += s[i];
if(ans.size() == 2) break;
}
if(ans.size() == 2) cout << ans << endl;
else puts("-1");
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}
贪心+构造。
就从0开始往上走,看看最远能走到哪,看代码。
#include<bits/stdc++.h>
#define PII pair<int, int>
using namespace std;
typedef long long ll;
const int maxn = 3e5 + 10;
int a[maxn], b[maxn];
inline void solve()
{
int n; scanf("%d", &n);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
if(n == 1)
{
puts("Yes");
return;
}
b[n] = 0; int pos = 0;
for(int i = n-1; i >= 1; i--)
{
b[i] = b[i+1]+1;
if(a[i] >= b[i]) continue;
else {
pos = i+1;
break;
}
}
for(int i = 1; i <= pos; i++)
{
b[i] = i-1;
if(b[i] <= a[i]) continue;
else {
puts("No");
return;
}
}
puts("Yes");
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}
这道题题意很坑,其实是要选择最前面的\(k\)个人。
假设原先的数字序列是一个\(deque\),那假如说前面拿\(i\)个,后面就会拿\(k-i\)个。
之后留下一个新的\(deque\)。
我排在第\(m\)位,我控制了\(k\)个人,所以我前面还有\(m-k-1\)个人拿才轮到我。
假设说前面有\(j\)个人拿,那后面就会拿\(m-k-1-j\)个人。
那这时候就要搞清楚,最开始的\(i\)和\(k-i\)是由我做决定的。
\(j,m-k-1-j\)是由别人做决定的。
最后会露出队头队尾,我会取一个较优的,这是我来做决定。
所以我们枚举\(i,j\),然后找最大。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 4e3 + 10;
int n, m, k;
int a[maxn];
inline void solve()
{
scanf("%d%d%d", &n, &m, &k);
for(int i = 1; i <= n; i++)
scanf("%d", &a[i]);
k = min(m-1, k);
int ans = 0;
for(int i = 0; i <= k; i++)
{
int tmp = 1e9;
for(int j = 0; j <= m-k-1; j++)
tmp = min(tmp, max(a[i+j+1], a[n-(k-i)-(m-k-1-j)]));
ans = max(ans, tmp);
}
cout << ans << endl;
}
int main()
{
int T; scanf("%d", &T);
while(T--) solve();
return 0;
}
阅读理解题,先看看题意。
规定两个字符串的\(anagrams\):两个字符串中间字符出现的次数一样。
规定\(reducible\),有一个\(k\geq2\),然后有\(s_1,t_1,s_2,t_2,...,s_k,t_k\)这几个子串都是对应的\(anagrams\)。
规定\(irreducible\),就是不\(reducible\)。
给定一个字符串,和\(q\)次询问,每次询问给定一个\(l,r\),问这个子串能否构造出一个\(irreducible\)。
思路:分类讨论
#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 10;
int q, cnt[26][maxn], l, r;
string s;
void solve()
{
scanf("%d%d", &l, &r);
l--, r--;
//长度为1
if(l == r) {
puts("YES");
return;
}
//左右不同
if(s[l] != s[r]){
puts("YES");
return;
}
//字符出现次数大于等于3
int tot = 0;
for(int i = 0; i < 26; i++)
{
int R = cnt[i][r], L = 0;
if(l > 0) L = cnt[i][l-1];
if(R - L > 0) tot++;
}
if(tot >= 3) {
puts("YES");
return;
}
puts("NO");
}
int main()
{
cin >> s; scanf("%d", &q);
for(int i = 0; i < s.size(); i++)
{
cnt[s[i]-'a'][i]++;
if(i > 0){
for(int j = 0; j < 26; j++)
cnt[j][i] += cnt[j][i-1];
}
}
while(q--) solve();
return 0;
}
你有n个灯,编号从1到n,每个灯的初始状态时关(0)或者开(1)。
你有\(k\)个集合\(A_1,...,A_k\),其中任意三个集合的交集为空集,集合控制着一些灯的开关。
每次操作你可以选择一个集合,然后改变这个集合控制的灯的状态。
询问你让前\(i\)个灯泡全部同时开着需要最少多少次操作,其中\(i+1\)~\(n\)的灯的状态可以不用理会。
qsc的视频题解https://www.bilibili.com/video/av86529667?p=5
由于任意三个集合的交集为空集,这就说明对于一个灯泡,他的开关最多只在两个集合当中。
也就是说:
对于每个开关集合,他有两个状态,一个是使用这个开关集合,一个是不使用这个开关集合。
我们先看第一个灯泡,同时假设这个灯泡由第\(i,j\)个集合管理,那么会有两个状态:
所以我们就可以根据上述关系用并查集缩点。
同时特殊处理由一个开关集合控制的灯泡情况,具体见代码,详细注释。
#include<bits/stdc++.h>
using namespace std;
const int maxn = 6e5+10;
int n, k, l[maxn][2];
int fa[maxn], sz[maxn];
string s;
int get_fa(int x){
if(x == fa[x]) return x;
return fa[x] = get_fa(fa[x]);
}
//计算x开和关两个选择操作的最小值
int calc(int x)
{
//y表示对应的开关集合(开/关)
int y = x<=k?x+k:x-k;
x = get_fa(x), y = get_fa(y);
//如果说有一个为0 那就只能进行选另一个操作了
//(只有在某个灯泡只被一个开关控制才会置0)
if(x == 0 || y == 0) return sz[x+y];
//返回较小值
return min(sz[x], sz[y]);
}
void merge_dis(int x, int y)
{
x = get_fa(x); y = get_fa(y);
if(y == 0){
swap(x, y);
} fa[y] = x;
if(x != 0) sz[x] += sz[y];
}
int main()
{
scanf("%d%d", &n, &k); cin >> s;
//种类带权并查集
//i表示第i个开关集合不使用的状态
//i+k表示第i个开关集合使用的状态
//sz表示花费是多少
//初始状态使用一次 所以置1
for(int i = 1; i <= k; i++)
fa[i] = i, fa[i+k] = i+k, sz[i+k] = 1;
//l(x, 0/1)=i 表示管理灯泡x的开关集合i
//最多有两个
for(int i = 1, c; i <= k; i++)
{
scanf("%d", &c);
for(int j = 0, x; j < c; j++)
{
scanf("%d", &x);
if(l[x][0] == 0) l[x][0] = i;
else l[x][1] = i;
}
}
int ans = 0;
for(int i = 1; i <= n; i++)
{
//第i个灯泡只由一个开关控制
if(l[i][1] == 0)
{
int x = l[i][0];
//如果x等于0 也就是没有关联
//任何的开关集合 那么这时候
//就不用考虑 continue
if(x)
{
//先减去上一次的答案
ans -= calc(x);
//如果说一开始就亮了 那么这个开关集合就不需要点
//同时也是一种标记 表示这种状态不可变
if(s[i-1] == '1') fa[get_fa(x+k)] = 0;
else fa[get_fa(x)] = 0;
ans += calc(x);
}
}
else //两个开关
{
//x y对应的开关集合
int x = l[i][0], y = l[i][1];
//如果一开始灯就是开的
if(s[i-1] == '1')
{
//这两个开关还没有关系
//如果有关系 那这个灯就开了
if(get_fa(x) != get_fa(y))
{
//先减去上一次的答案
ans -= calc(x);
ans -= calc(y);
//缩点
//两个开关同时不使用
merge_dis(x, y);
//两个开关同时使用
merge_dis(x+k, y+k);
//然后再加上这次的结果
ans += calc(x);
}
}
//如果灯是关的
else
{
if(get_fa(x+k) != get_fa(y))
{
ans -= calc(x);
ans -= calc(y);
merge_dis(x+k, y);
merge_dis(x, y+k);
ans += calc(x);
}
}
}
cout << ans << endl;
}
return 0;
}
Codeforces Round #616 (Div. 2)解题报告
标签:can sharp red puts ble bre pac 最小 多少
原文地址:https://www.cnblogs.com/zxytxdy/p/12258265.html