Nov 7

滑铁卢式的惨败。

T1 P10205 [JOI 2024 Final] 室温 / Room Temperature

场上并没能正确做出来。

当时同样是 %t 处理了每个 a,然后就想着取一下左右端点,答案是中间就行了。

这个想法大抵上是正确的,但也只是大抵上正确。

我们可能会有情况如下。

如果将最左边的去一件衣服(+t),让他成为新的右端点,下一个点成为新的左端点,无法保证这个情况比之前说的做法劣。

所以我们也要考虑上就是了。

排个序,枚举左右相邻点为左右端点算就行。

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MN=1e6+116;
int a[MN], n, t, ans;
void Read(){
	cin>>n>>t;
	for(int i=1; i<=n; ++i) cin>>a[i];
	for(int i=1; i<=n; ++i) a[i]%=t;
	return;
}
void Solve(){
	Read(); sort(a+1,a+n+1);
	ans=(a[n]-a[1]+1)/2;
	for(int i=1; i<=n; ++i){
		ans=min(ans,(a[i]+t-a[i+1]+1)/2);
	}
	cout<<ans<<'\n';
	return;
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	Solve();
	return 0;
}

T2 【MX-X7-T3】[LSOT-3] 寄存器

我并没有做出来,因为我并没有找出来正确的删除逻辑。

一个我的错误想法,这个问题就是以任意黑色节点为根跑出来一个尽可能小的,包含所有黑色的联通快,之后再将里边白色的联通块删除。

这个明显在小数据或者树成链问题是不大的,但是考虑以下的情况。

树分三层,根是黑色,三个儿子是白色,每个儿子都有一个儿子,儿子的儿子是黑色。

这种情况我们按照之前的思路是需要四次的,然而存在一个三次的操作方法。

我们先电整张图,之后断掉儿子与儿子的儿子间的边,再电一次剩下的图,最后电一下根节点。

于是想分层一样的,我们就成功得出了一种优于之前思路的,按照分层进行的手段。

那么显然的,我们只需要找出来这棵树最多能被分层多少图就行了。

我们把不同的颜色之间连的边的边权设为 1, 把相同颜色之间连的边边权设为 0, 之后正常跑树的直径,这个样子直径的每一个单位长度就代表着一次分层。

我们从这个直径的重点开始就行了,答案是 (len+1)/2.

代码↓

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MN=3e6+316;
struct Node{
	int nxt, to;
}node[MN];
int head[MN], tottt;
void insert(int u, int v){
	node[++tottt].to=v;
	node[tottt].nxt=head[u];
	head[u]=tottt; return;
}
int n, a[MN], cnt1=0;
void Read(){
	cin>>n;
	for(int i=1; i<=n; ++i){
		cin>>a[i];
		cnt1+=a[i];
	}
	for(int i=1; i<n; ++i){
		int u, v;
		cin>>u>>v;
		insert(u,v);
		insert(v,u);
	}
}
int stt, maxn=0;
void dfs(int u, int father, int depth){
	if(a[u]!=a[father]) depth++;
	if(a[u]==1&&depth>maxn){
		maxn=depth; stt=u;
	}
	for(int i=head[u];i;i=node[i].nxt){
		int v=node[i].to;
		if(v==father) continue;
		dfs(v,u,depth);
	}
}
void Solve(){
	Read();
	if(cnt1==0){
		cout<<0<<'\n';
		return;
	}
	dfs(1,0,0); maxn=0;
	dfs(stt,0,0);
	//cout<<maxn<<'\n';
	cout<<(maxn+1)/2<<'\n';
	return;
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	Solve();
	return 0;
}

T3 P12649 [KOI 2024 Round 2] 收集彩球

一道神秘图论建模题。

把每个颜色看成是点,上边连下边。

统计联通快四种情况:成链,成环,自环,其他。

其他即两个以上出度为 0,这个就是无解。

代码↓

点击查看代码
#include <bits/stdc++.h>
using namespace std;
const int MN=1e6+116;
struct Node{
	int nxt, to;
}node[MN];
int head[MN], tottt=1;
void insert(int u, int v){
	node[++tottt].to=v;
	node[tottt].nxt=head[u];
	head[u]=tottt; return;
}
int n, a[MN], b[MN];
int ans=0, vis[MN], deg[MN];
int dfs(int u){
	int res=0;
	if(deg[u]==0) res++;
	vis[u]=true;
	for(int i=head[u];i;i=node[i].nxt){
		int v=node[i].to;
		if(vis[v]) continue;
		res+=dfs(v);
	} 
	return res;
}
void Read(){
	cin>>n;
	for(int i=1; i<=n; ++i) cin>>a[i]>>b[i];
	return;
}
void Solve(){
	Read(); ans=n;
	for(int i=1; i<=n; ++i){
		insert(a[i],b[i]);
		insert(b[i],a[i]);
		deg[a[i]]++;
		if(a[i]==b[i]){
			vis[a[i]]=true;
			ans--;
		}
	}
	for(int i=1; i<=n; ++i){
		if(vis[i]) continue;
		int res=dfs(i);
		if(res>=2){
			cout<<-1<<'\n'; return;
		}
		ans++;
	}
	cout<<ans<<'\n';
	return;
}
int main(){
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);
	Solve();
	return 0;
}
posted @ 2025-11-07 14:30  BaiBaiShaFeng  阅读(0)  评论(0)    收藏  举报
Sakana Widget右下角定位