A 题:A - B = C
题目链接
https://atcoder.jp/contests/arc112/tasks/arc112_a。
题解
本题不难,如果数据量不大的话,本题可以使用暴力枚举的方法来解决。也就是在 [L, R] 之间枚举 A 和 B,并计算 C=A-B,这样算法的时间复杂度是 的。
我们看看本题的数据范围,本题给了 T 个样例,T 的最大值是 2e4。[L, R] 的最大值是 1e6。如果我们进行暴力枚举的话,计算量将达到 ,这样的计算量,我们肯定是没有办法在 1 秒内完成的。为了完成这个任务,本题需要一个 O(1) 的算法,也就是说,根据给定的 [L, R] 计算出对应的三元组。这样本题的时间复杂度将变为
。因此本题变为一个纯粹的数学题。
本题是要求在 [L, R] 的范围内,找出所有的三元组 {A, B, C},这三元组满足两个条件:
1、。
2、。
根据上面两个条件,我们可以写出满足的三元组个数为:。这个计算结果不难,自己推导一下。
数据范围分析
根据题目提供的数据范围,很明显需要使用 long long。
AC 参考代码
#include <iostream>
using namespace std;
typedef long long ll;
int main() {
int t;
cin>>t;
while (t--) {
ll l,r;
cin>>l>>r;
ll ans=0;
if (r>=2*l) {
ans+=(r-2*l+1)*(r-2*l+2)/2;
}
cout<<ans<<"\n";
}
return 0;
}
B题:B - -- - B
题目链接
https://atcoder.jp/contests/arc112/tasks/arc112_b。
题解
如果数据量小,本题可以使用 BFS 来完成。但是本题数据范围,C 最大为 1e18,看到这个数据,不需要过多解释,BFS 一定是 TLE。因此本题需要一个 O(1) 时间复杂度。这样本题又又变成了一个数学题。找规律。
具体看 AC 代码吧。不想写太多。
数据范围分析
没什么特别解释。long long 走起。
AC 参考代码
#include <iostream>
using namespace std;
typedef long long ll;
int main(){
ll b,c;
cin>>b>>c;
//特例处理
if (1==c){
if (b) {
cout<<"2\n";
} else {
cout<<"1\n";
}
return 0;
}
ll lx,ly,rx,ry;
lx=b-c/2;
rx=b+c/2-1;
ly=-b-(c-1)/2;
ry=-b+(c-1)/2;
if (rx<ly||ry<lx){
cout<<rx-lx+ry-ly+2<<"\n";
return 0;
}
if (rx<ry) {
rx=ry;
}
if (ly<lx) {
lx=ly;
}
cout<<rx-lx+1<<"\n";
return 0;
}
C题:C - DFS Game
题目链接
https://atcoder.jp/contests/arc112/tasks/arc112_c。
题解
都直接告诉你了,我们快乐的 DFS 吧。
数据范围分析
n 的最大值为 1e5,v 的范围是 [1, n],用 int 够了。
AC 参考代码
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
const int MAXN=1e5+4;
int fir[MAXN],nex[MAXN],to[MAXN],f[MAXN],sz[MAXN],tot;
struct node{
int x,id;
bool operator<(const node &i) const{
return x>i.x;
}
}st[MAXN];
void add(int u,int v) {
nex[++tot]=fir[u];
fir[u]=tot;
to[tot]=v;
}
void dfs(int u) {
int s1=0,s2=0,top=0;
sz[u]=f[u]=1;
for (int i=fir[u];i;i=nex[i]) {
dfs(to[i]);
}
for (int i=fir[u];i;i=nex[i]) {
sz[u]+=sz[to[i]];
if (sz[to[i]]-f[to[i]]>=f[to[i]]&&(sz[to[i]]&1)==0) {
f[u]+=f[to[i]];
} else {
if (sz[to[i]]&1) {
st[++top]=(node){sz[to[i]]-f[to[i]]*2,to[i]};
} else {
s1+=f[to[i]];
s2+=sz[to[i]]-f[to[i]];
}
}
}
sort(st+1,st+1+top);
for (int i=1;i<=top;++i) {
if (i&1) {
f[u]+=f[st[i].id];
} else {
f[u]+=sz[st[i].id]-f[st[i].id];
}
}
if (top&1) {
f[u]+=s2;
} else {
f[u]+=s1;
}
}
int main() {
int n, u;
cin>>n;
for(int i=2;i<=n;++i) {
cin>>u;
add(u,i);
}
dfs(1);
cout<<f[1]<<"\n";
return 0;
}
D题:D - Skate
题目链接
https://atcoder.jp/contests/arc112/tasks/arc112_d。
题解
不就是一个数据结构的并查集(DSU)问题。我们只需要根据题意建立 DSU 关系,然后再行遍历、列遍历 DSU 关系即可。
DSU 方面的,可以参考一下 AtCoder 在 Github 上提供的 AC-library 这个库,对应的 Github 链接为:https://github.com/atcoder/ac-library。
考虑到国内 Github 的速度,下面是 DSU 的源码。
#ifndef ATCODER_DSU_HPP
#define ATCODER_DSU_HPP 1
#include <algorithm>
#include <cassert>
#include <vector>
namespace atcoder {
// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
public:
dsu() : _n(0) {}
explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}
int merge(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
return x;
}
bool same(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
return leader(a) == leader(b);
}
int leader(int a) {
assert(0 <= a && a < _n);
if (parent_or_size[a] < 0) return a;
return parent_or_size[a] = leader(parent_or_size[a]);
}
int size(int a) {
assert(0 <= a && a < _n);
return -parent_or_size[leader(a)];
}
std::vector<std::vector<int>> groups() {
std::vector<int> leader_buf(_n), group_size(_n);
for (int i = 0; i < _n; i++) {
leader_buf[i] = leader(i);
group_size[leader_buf[i]]++;
}
std::vector<std::vector<int>> result(_n);
for (int i = 0; i < _n; i++) {
result[i].reserve(group_size[i]);
}
for (int i = 0; i < _n; i++) {
result[leader_buf[i]].push_back(i);
}
result.erase(
std::remove_if(result.begin(), result.end(),
[&](const std::vector<int>& v) { return v.empty(); }),
result.end());
return result;
}
private:
int _n;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
};
} // namespace atcoder
#endif // ATCODER_DSU_HPP
AC 参考代码
#include <iostream>
#include <algorithm>
#include <cassert>
#include <vector>
#include <unordered_set>
namespace atcoder {
// Implement (union by size) + (path compression)
// Reference:
// Zvi Galil and Giuseppe F. Italiano,
// Data structures and algorithms for disjoint set union problems
struct dsu {
public:
dsu() : _n(0) {}
explicit dsu(int n) : _n(n), parent_or_size(n, -1) {}
int merge(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
int x = leader(a), y = leader(b);
if (x == y) return x;
if (-parent_or_size[x] < -parent_or_size[y]) std::swap(x, y);
parent_or_size[x] += parent_or_size[y];
parent_or_size[y] = x;
return x;
}
bool same(int a, int b) {
assert(0 <= a && a < _n);
assert(0 <= b && b < _n);
return leader(a) == leader(b);
}
int leader(int a) {
assert(0 <= a && a < _n);
if (parent_or_size[a] < 0) return a;
return parent_or_size[a] = leader(parent_or_size[a]);
}
int size(int a) {
assert(0 <= a && a < _n);
return -parent_or_size[leader(a)];
}
std::vector<std::vector<int>> groups() {
std::vector<int> leader_buf(_n), group_size(_n);
for (int i = 0; i < _n; i++) {
leader_buf[i] = leader(i);
group_size[leader_buf[i]]++;
}
std::vector<std::vector<int>> result(_n);
for (int i = 0; i < _n; i++) {
result[i].reserve(group_size[i]);
}
for (int i = 0; i < _n; i++) {
result[leader_buf[i]].push_back(i);
}
result.erase(
std::remove_if(result.begin(), result.end(),
[&](const std::vector<int>& v) { return v.empty(); }),
result.end());
return result;
}
private:
int _n;
// root node: -1 * component size
// otherwise: parent
std::vector<int> parent_or_size;
};
} // namespace atcoder
using namespace std;
using namespace atcoder;
int main() {
int h, w;
cin >> h >> w;
vector<string> s(h);
for (int i=0; i<h; i++) {
cin >> s[i];
}
//增加边界条件
s[0][0] = s[0][w - 1] = s[h - 1][0] = s[h - 1][w - 1] = '#';
//初始化DSU
dsu d(h + w);
//建立DSU关系
for (int r = 0; r < h; ++r) {
for (int c = 0; c < w; ++c) {
if (s[r][c] == '#') {
d.merge(r, h + c);
}
}
}
//遍历DSU
unordered_set<int> row, col;
//行遍历
for (int r = 0; r < h; ++r) {
row.insert(d.leader(r));
}
//列遍历
for (int c = 0; c < w; ++c) {
col.insert(d.leader(h + c));
}
cout << min(row.size() - 1, col.size() - 1) << "\n";
return 0;
}