Codeforces Round #819 解题报告
A. Mainak and Array
题意 :给定一个数组,要求选定一个区间,并将该区间的数循环右推k个单位,问最大的\(a_n - a_1\) 的值
分析:因为要使\(a_n - a_1\)最大,那就要让选定的区间至少包含一个端点,考虑三种情况:只含一个端点的(1或n),两个区间都包含,枚举一下
ac 代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <random>
//#pragma GCC optimize(3,"Ofast","inline")
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
using namespace std;
typedef unsigned long long uLL;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 10010,M = 10010,INF = 0x3f3f3f3f,mod = 998244353;
const double DNF = 0x7f7f7f7f7f7f7f7f,pi = acos(-1.0),eps = 1e-6;
const long long LNF = 0x3f3f3f3f3f3f3f3f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n;
vector<int> a(n + 2);
for(int i = 1;i <= n;i ++) cin >> a[i];
a[n + 1] = INF;
int ans = a[n] - a[1],maxv = 0,minv = INF;
for(int i = 1;i <= n;i ++)
{
ans = max(ans,a[i] - a[i + 1]);
maxv = max(a[i],maxv);
minv = min(minv,a[i]);
}
ans = max({maxv - a[1],a[n] - minv,ans});
cout << ans << endl;
}
return 0;
}
B. Mainak and Interesting Sequence
题意 :给定两个数字,n 和 m,要求构造一个长度为n的数组,总和为m,并且满足对于任一元素,数组中其他严格小于他的数的异或和为0
分析 :考虑n - 1个一样的数,和一个比他们大的数字,当n - 1为偶数时,这些数异或值异或为0,直接输出就好,当n - 1为奇数时,要考虑m的奇偶性,当m为偶数时无法凑出来,奇数可以
ac代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <random>
//#pragma GCC optimize(3,"Ofast","inline")
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
using namespace std;
typedef unsigned long long uLL;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 10010,M = 10010,INF = 0x3f3f3f3f,mod = 998244353;
const double DNF = 0x7f7f7f7f7f7f7f7f,pi = acos(-1.0),eps = 1e-6;
const long long LNF = 0x3f3f3f3f3f3f3f3f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n >> m;
if(n > m) cout << "No" << endl;
else
{
if(n % 2)
{
cout << "Yes" << endl;
int x = m / n, sum = 0;
for(int i = 1;i < n;i ++) cout << x << " ",sum += x;
cout << m - sum << endl;
}
else
{
if(m % 2) cout << "No" << endl;
else
{
cout << "Yes" << endl;
int sum = 0;
for(int i = 1;i < n - 1;i ++) cout << 1 << ' ',sum ++;
cout << (m - sum) / 2 << ' ' << (m - sum) / 2 << endl;
}
}
}
}
return 0;
}
C. Jatayu's Balanced Bracket Sequence
题意 :给定一个长度为2n的合法括号序列,每个字符代表图中的一个顶点,对于字串s[l...r],,如果他是一个合法的括号序列,那么就代表顶点l和r之间有一条无向边,问该序列所代表的图中,有几个连通块
分析 :AB是合法序列,(A)也是合法序列,但是(A)不能减少连通块的个数,AB,则A最左边的 ( 和B最右边的 ) 可以构成合法序列,连通块-1
一开始有n 个连通块,假如碰到 )( 连通块个数 -1
ac代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <random>
//#pragma GCC optimize(3,"Ofast","inline")
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
using namespace std;
typedef unsigned long long uLL;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 10010,M = 10010,INF = 0x3f3f3f3f,mod = 998244353;
const double DNF = 0x7f7f7f7f7f7f7f7f,pi = acos(-1.0),eps = 1e-6;
const long long LNF = 0x3f3f3f3f3f3f3f3f;
int n,m,k,t;
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n;
string s;
cin >> s;
s = ' ' + s;
int x = 0,y = 0;
for(int i = 1;i <= n + n;i ++)
{
if(s[i] == '(')
{
x ++;
}
else if(i < n + n)
{
if(s[i] == ')' && s[i + 1] == '(') y ++;
}
}
cout << x - y << endl;
}
return 0;
}
D. Edge Split
题意 : 给定一个无向图,n个节点,m条边,其中\(n - 1 \leq m\leq n + 2\),现要求将所有边染成两种颜色,使得两种颜色所构成的图的连通块之和最小
分析 : 要得到满足题意的图,关键在于使两张图都没有环,我们可以先求出一颗生成树,将所有树边染成一种颜色,可以发现,只有\(m = n + 2\) 时,剩下的图才可能构成环,所以只需要处理这种情况,判环可以用set去重来解决,因为剩下三条边,如果只存在三个点,则必程环路,只需将环的某个边染成其他颜色,在看另一张图,一定因为加了yi条边而形成了环路,选择一个环路上的点保留一条路径为原来的颜色,其他边都染成另种颜色
ac代码
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <queue>
#include <map>
#include <vector>
#include <stack>
#include <set>
#include <sstream>
#include <fstream>
#include <cmath>
#include <iomanip>
#include <bitset>
#include <unordered_map>
#include <unordered_set>
#include <random>
//#pragma GCC optimize(3,"Ofast","inline")
#define x first
#define y second
#define ios ios::sync_with_stdio(false),cin.tie(0);
#define endl '\n'
#define pb push_back
#define all(x) x.begin(),x.end()
#define all1(x) x.begin()+1,x.end()
using namespace std;
typedef unsigned long long uLL;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 200010,M = 10010,INF = 0x3f3f3f3f,mod = 998244353;
const double DNF = 0x7f7f7f7f7f7f7f7f,pi = acos(-1.0),eps = 1e-6;
const long long LNF = 0x3f3f3f3f3f3f3f3f;
int n,m,k,t;
int p[N];
struct Edge
{
int x,y,id;
};
int find(int x)
{
if(x != p[x]) return p[x] = find(p[x]);
return x;
}
int main()
{
ios;
cin >> t;
while(t --)
{
cin >> n >> m;
vector<Edge> edges(m + 1),x,y;
vector<int> ans(m + 1);
set<int> s;
for(int i = 1;i <= n;i ++) p[i] = i;
for(int i = 1;i <= m;i ++) cin >> edges[i].x >> edges[i].y,edges[i].id = i;
for(int i = 1;i <= m;i ++)
{
int a = find(edges[i].x), b = find(edges[i].y);
if(a != b)
{
ans[i] = 1;
p[a] = b;
x.pb(edges[i]);
}
else
{
s.insert(edges[i].x),s.insert(edges[i].y);
y.pb(edges[i]);
}
}
if(m == n + 2)
{
if(s.size() == 3)
{
int v = y[0].x;
ans[y[0].id] = 1;
for(auto x : x) if(x.x == v || x.y == v) ans[x.id] = 0;
}
}
for(int i = 1;i <= m;i ++) cout << ans[i] ;
cout << endl;
}
return 0;
}