萌新的第一篇题解,就写一点和别的大佬不一样的吧。😀
D.小红走迷宫
此题我一看就想到了并查集,而并没有想到其他(😂)。于是试了一下,没想到还真搞出来了,时间非常充裕。
#include <iostream>
#define MAX (int)5e5+5
#define For(i,a,b) for(int i=a;i<b;i++)
using namespace std;
int set[MAX];
bool trap[MAX];
int find(int i) {
if (set[i] == i) {
return i;
}
return set[i] = find(set[i]);
}
void unite(int i, int j) {
int root_i = find(i);
int root_j = find(j);
if (root_i != root_j) {
set[root_i] = root_j;
}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
int n,m,x;
cin >> n >> m >> x;
For(i,0,n+1) set[i]=i;
For(i,0,x){int tmp;cin >> tmp;trap[tmp]=1;}
For(i,0,m){
int u,v;
cin >> u >> v;
if(!trap[u] && !trap[v])
unite(u,v);
}
for(int i = 1;i <= n;i++){
if(find(i) == find(1) ) cout << i << ' ';
}
}
E.小苯的刷怪笼
此题就是一个思维题,完全可以从数学角度推理出符合条件的一种情况。
特殊情况
先讨论最特殊的一种情况:,此时只需要
即有解,否则无解。
其他情况
首先我们对每次攻击进行分类(分别用x(攻击相邻两个怪物),y(只攻击一个怪物))经过分析很容易列出两个方程:
顺手我们就可以解出x,y的值:
然后根据x,y的定义可以得到有解的一个条件是 。
然后我们考虑 ,我们可以把
对应的情况想象成一个长为
,宽为
的矩形物块,
对应的情况则想象成边长为
的正方形物块,用这些物块来在一个长为
的场地上进行堆叠,然后我们肯定是先堆叠矩形长条,先只堆一层,可以发现,当
大到而一定程度时,就需要多于一个的正方形来凑数,那么这些正方形就可以合成矩形,这回减少总数k,所以无解,而临界情况是什么呢?那就是刚好拿出两个正方形物块来凑数,此时,我们就可以得出第二个有解的条件
然后我们在考虑如何继续操作。
为了简单起见,我们就令矩形物块在堆叠过程中不会出现一个矩形物块同时放在两个物块上。
那么我们就可以得到一种堆法:
然后写出对应代码即可
#include <iostream>
using namespace std;
typedef long long ll;
#define MAX (int)2e5+5
ll blood[MAX];
int main(){
ll n,a,k;
cin >> n >> a >> k;
ll i = a - k, m = 2*k - a;
if(i < 0 || m < 0 || n - 2*i >= 2) { cout << -1; return 0; }
if(n == 1) {
if( k == a) cout << a;
else cout << -1;
return 0;
}
for(int j = 1; j <= (2*i) % (n/2*2);j++) blood[j] = (2*i)/(n/2*2) + 1;
for(int j = (2*i) % (n/2*2) + 1;j <= n/2*2;j++) blood[j] = (2*i)/(n/2*2);
blood[n] += m;
for(int j=1;j <= n;j++ ) cout << blood[j] << ' ';
}