[CSP-S 2024] 决斗 题解

[CSP-S 2024] 决斗 题解


知识点

贪心,路径压缩并查集,Dilworth 定理

题意简述

\(n\) 个怪物战斗,其值分别为 \(a_1,a_2,\ldots\),值大的能打败小的,每个怪兽只能攻击一次,问最少能剩下几个怪兽。

分析

贪心

贪心一下,从小到大排序,然后能往前攻击的就攻击,这样保证能攻击到最多。可以用路径压缩并查集优化。

Dilworth 定理

再或者,如果你学过 Dilworth 定理,你就会发现答案就是众数在序列中出现的次数,那就更简单了,用数组统计一下即可。

代码

贪心

时间复杂度:\(O(n\log_2{n})\),空间复杂度:\(O(n)\)

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[i=(g)[i].nxt].v)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
using namespace std;
constexpr int N(1e5+10);
bool vis[N];
int n,it,ans;
int a[N];
struct DSU {
	int fa[N];
	void Init() {
		FOR(i,1,n)fa[i]=i;
	}
	int get(int x) {
		return fa[x]^x?fa[x]=get(fa[x]):x;
	}
	void merge(int u,int v) {
		fa[get(u)]=get(v);
	}
} dsu;
signed main() {
#ifdef Plus_Cat
	freopen(Plus_Cat ".in","r",stdin),freopen(Plus_Cat ".out","w",stdout);
#endif
	cin>>n,dsu.Init();
	FOR(i,1,n)cin>>a[i];
	sort(a+1,a+n+1);
	FOR(i,1,n) {
		while(it<n&&a[it+1]<a[i])++it;
		if(!it)continue;
		int pos(dsu.get(it));
		if(pos)vis[pos]=1,dsu.merge(pos,pos-1);
	}
	FOR(i,1,n)ans+=!vis[i];
	cout<<ans<<endl;
	return 0;
}

Dilworth 定理

时间复杂度:\(O(n)\),空间复杂度:\(O(n)\)

#include<bits/stdc++.h>
#define INF 0x3f3f3f3f
#define ll long long
#define RCL(a,b,c,d) memset(a,b,sizeof(c)*(d))
#define FOR(i,a,b) for(int i(a);i<=(int)(b);++i)
#define DOR(i,a,b) for(int i(a);i>=(int)(b);--i)
#define tomax(a,...) ((a)=max({(a),__VA_ARGS__}))
#define tomin(a,...) ((a)=min({(a),__VA_ARGS__}))
#define EDGE(g,i,x,y) for(int i=(g).h[(x)],y=(g)[(i)].v;~i;y=(g)[i=(g)[i].nxt].v)
#define main Main();signed main(){ios::sync_with_stdio(0);cin.tie(0),cout.tie(0);return Main();}signed Main
using namespace std;
namespace IOstream {
#define getc() getchar()
#define putc(ch) putchar(ch)
#define isdigit(ch) ('0'<=(ch)&&(ch)<='9')
	template<class T>void rd(T &x) {
		static bool sign(0);
		static char ch(0);
		for(x=0,sign=0,ch=getc(); !isdigit(ch); ch=getc())if(ch=='-')sign=1;
		for(; isdigit(ch); x=(x<<1)+(x<<3)+(ch^'0'),ch=getc());
		if(sign)x=-x;
	}
	template<class T>void wr(T x,const char End='\n') {
		static int top(0);
		static int st[50];
		do st[++top]=x%10,x/=10;
		while(x);
		while(top)putc(st[top]^'0'),--top;
		putc(End);
	}
} using namespace IOstream;
constexpr int N(1e5+10);
int n,ans;
int cnt[N];
signed main() {
	rd(n);
	FOR(i,1,n) {
		int a;
		rd(a),++cnt[a];
	}
	FOR(i,1,N-5)tomax(ans,cnt[i]);
	wr(ans);
	return 0;
}

posted @ 2024-11-13 14:01  plus_cat  阅读(6)  评论(0编辑  收藏  举报