A - Nine
题意:给一个3*3的方格,给A和B两个数,问是否水平相邻。
思路:直接模拟
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int a,b;
cin >> a >> b;
int mn = min(a,b), mx = max(a,b);
int f = 0;
if(mn == 1 && mx == 2) f = 1;
else if(mn == 2 && mx == 3) f = 1;
else if(mn == 4 && mx == 5) f = 1;
else if(mn == 5 && mx == 6) f = 1;
else if(mn == 7 && mx == 8) f = 1;
else if(mn == 8 && mx == 9) f = 1;
cout << (f ? "Yes" : "No");
return 0;
}
B - Rotate
题意:给一个二维数组a,对它最外一层进行顺时针旋转移动一格。输出移动后的二维数组。
思路:我用两个二维数组,进行模拟。
#include<bits/stdc++.h>
using namespace std;
const int N = 100010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;
int a[110][110], b[110][110];
int main()
{
// ios::sync_with_stdio(0);
// cin.tie(0);
int n;
cin >> n;
for(int i = 1; i <= n; i++ )
for(int j = 1; j <= n; j ++ )
{
scanf("%1d", &a[i][j]);
b[i][j] = a[i][j];
}
// a[1][1] = b[2][1];
//上面一层向右移
for(int i = 1; i <= n; i ++ )
a[1][i + 1] = b[1][i];
//右边一层向下移
for(int i = 1; i <= n; i ++ )
a[i + 1][n] = b[i][n];
for(int i = 1; i <= n - 1; i ++ )
a[n][i] = b[n][i + 1];
//下面一层向左移
for(int i = 1; i <= n - 1; i ++ )
a[i][1] = b[i + 1][1];
//左边一层向上移
for(int i = 1; i <= n; i ++ )
{
for(int j = 1; j <= n; j ++ )
cout << a[i][j];
cout << '\n';
}
return 0;
}
C - Medicine
题意:有n中不同的药要吃,某一种药连续天吃片,问最早哪一天吃的药的数量小于等于k片。
思路:假设最后吃到p天,画图可以看出1~p吃药的数量是单调不递增的,那么二分天数,如果这天吃的药小于等于k片向左找,否则向右找。
#include<bits/stdc++.h>
using namespace std;
const int N = 300010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;
ll n, k;
ll a[N],b[N];
bool check(ll x)
{
ll sum = 0;
for(int i = 1; i <= n; i ++ )
if(a[i] >= x) sum += b[i];
return sum <= k;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> k;
for(int i = 1; i <= n; i ++ ) cin >> a[i] >> b[i];
ll l = 1, r = 1e10;
while(l < r)
{
ll mid = (l + r) >> 1;
if(check(mid)) r = mid;
else l = mid + 1;
}
cout << l << '\n';
return 0;
}
D - Add One Edge
题意:1~的点互相连通,~的点互相连通,问加一条边,求1到的最短距离为d,我们要使d尽可能的大。
思路:对于点1,分别跑bfs,并记录各自的到某个点的最大值a,b,加一条到这两个点,那么使d不就最大了,答案a+b+1。
题解:
#include<bits/stdc++.h>
using namespace std;
const int N = 300010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;
vector<int> g[N];
// int l[N], r[N];
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
int a, b, m;
cin >> a >> b >> m;
for(int i = 0; i < m; i ++ )
{
int x, y;
cin >> x >> y;
g[x].push_back(y);
g[y].push_back(x);
}
queue<pii> q;
vector<int> v(a + b + 10);
v[1] = 1;
q.push({1, 0});
int lmx = 0, rmx = 0;
while(q.size())
{
auto t = q.front(); q.pop();
int p = t.first, d = t.second;
lmx = max(lmx, d);
for(int i = 0; i < g[p].size(); i ++ )
{
int j = g[p][i];
if(!v[j])
{
v[j] = 1;
q.push({j, d + 1});
}
}
}
for(auto i : v) i = 0;
v[a + b] = 1;
q.push({a+b, 0});
while(q.size())
{
auto t = q.front(); q.pop();
int p = t.first, d = t.second;
rmx = max(rmx, d);
for(int i = 0; i < g[p].size(); i ++ )
{
int j = g[p][i];
if(!v[j])
{
v[j] = 1;
q.push({j, d + 1});
}
}
}
// cout << lmx << ' ' << rmx << endl;
cout << lmx + rmx + 1 << '\n';
return 0;
}
E - Family and Insurance
题意:一棵树,父节点x买了保险对于y后代都覆盖有保险,问至少多少人有一份保险。
思路:刚开始是想的给一个操作去dfs一次,但是会超时,就一直想怎么优化。对于每个人只要有买或受到保险覆盖即可,将所有操作后代拿一个数组p保存,对每一个节点去dfs,并用vis数组记录是否访问,对于当前节点u对后代产生保x,设cnt为从父节点对后代的影响,x = max(cnt, p[u]),保证每个节点只会访问一次。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 300010, mod = 1e9 + 7;
typedef long long ll;
typedef pair<int,int> pii;
int n, m;
vector<int> g[N];
int p[N];
int ans;
int v[N];
void dfs(int u, int cnt)
{
int cur = max(cnt, p[u]);
v[u] = 1;
if(cur >= 0) ans++;
else return ;
for(int i = 0; i < g[u].size(); i ++ )
{
int j = g[u][i];
if(!v[j])
{
dfs(j, cur - 1);
}
}
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cin >> n >> m;
for(int i = 2; i <= n; i ++ )
{
int x;
cin >> x;
g[x].push_back(i);
}
memset(p, -1, sizeof p);
for(int i = 0; i < m; i ++ )
{
int x,y;
cin >> x >> y;
p[x] = max(y, p[x]);
}
for(int i = 1; i <= n; i ++ )
if(!v[i]) dfs(i, p[i]);
cout << ans << '\n';
return 0;
}