CF每日4题(1500-1700)

经验+4

  • 103B 克苏鲁可爱捏+发现图点和边的数量规律
  • 1198A 滑动窗口
  • 255C 二维dp求最小值
  • 1496C a x = ⌈ a x a y ⌉ a_x=\lceil{a_x\over a_y}\rceil ax=⌈ayax⌉,用 \sqrt{} 优化次数

103B 图 并查集1500

cpp 复制代码
const int N=1e6+10,mod=1e9+7,inf=1e9+10;
int fa[N];
int findf(int x){
	if(fa[x]==x)return x;
	return fa[x]=findf(fa[x]);
}
void merge(int x,int y){
	int fx=findf(x),fy=findf(y);
	if(fx==fy)return;
	fa[fy]=fa[fx];
}
void solve(){
	int n,m;cin>>n>>m;
	forr(i,1,n)fa[i]=i;
	forr(i,1,m){
		int u,v;
		cin>>u>>v;
		merge(u,v);
	}
	if(n==m){//使用并查集确认是不是只有一个连通块
		int fg=0;
		forr(i,1,n)fg+=(fa[i]==i);
		
		cout<<(fg==1?"FHTAGN!":"NO")<<endl;
	}else cout<<"NO"<<endl;
}

1198A 滑动窗口 1600

题意:改变最少的数,让数组中的不同数值数为给定值

注意留下的数应该大小上是连续的,因为强度值要在 l , r l,r l,r范围内

所以采用滑动窗口

cpp 复制代码
map<int,int>mp;
set<int>s;
void solve(){
	int n,m;cin>>n>>m;
	vector<int>a(n+1);

	forr(i,1,n){
		cin>>a[i];
		mp[a[i]]++;
		s.insert(a[i]);
	}
	
	int k=8*m/n;
	if(k>=31)return cout<<0<<endl,void();//2^k>4e5 溢出输出0
	k=(1<<k);//最大种数
	if(k>=s.size())return cout<<0<<endl,void();//可以容下全部数 不用改
	
	//滑动窗口
	int ans=0,sm=0;
	auto l=s.begin(),r=s.begin();
	forr(i,1,k){
		sm+=mp[*r];
		r++;
	}
	while (r!=s.end())
	{
		sm=sm-mp[*l]+mp[*r];
		l++,r++;
		ans=max(sm,ans);
	}
	cout<<n-ans<<endl;
}

225C dp 1700

cpp 复制代码
//从前向后 收集型
//从i-1更新i i可以变色,或延续不变色
string s[N];
int cnt[N][2],dp[N][N][2];//第i列 宽度j 颜色c
void solve(){
	int n,m,x,y;cin>>n>>m>>x>>y;
	memset(dp,0x3f,sizeof dp);//要求最小值,注意初始化为inf
	forr(i,1,n){
		cin>>s[i];
		s[i]=' '+s[i];
	}
	forr(i,1,m){
		forr(j,1,n){
			cnt[i][0]+=(s[j][i]=='.');
			cnt[i][1]+=(s[j][i]=='#');
		}
	}

	dp[1][1][0]=cnt[1][0],dp[1][1][1]=cnt[1][1];//第一个不用看前面的状态
	forr(i,2,m){
		forr(c,0,1){
			forr(j,x,y){//变色
				dp[i][1][c]=min(dp[i-1][j][c^1]+cnt[i][c],dp[i][1][c]);
			}
			forr(j,2,y){//不变色
				dp[i][j][c]=dp[i-1][j-1][c]+cnt[i][c];
			}
		}
	}
	
	int ans=0x3f3f3f3f;
	forr(j,x,y){
		ans=min({dp[m][j][0],dp[m][j][1],ans});
	}
	cout<<ans<<endl;
}

另有dalao前面更新后面的思路

1469C 思维 数学 1700


有点红温,死磕log的处理方法,但是 l o g 2 2 e 5 > 17 log_22e5>17 log22e5>17,一直想着怎么优化才好,没换个思路。

看题解发现利用 n \sqrt n n 就好,2e5五层 \sqrt{} 就到1了

  • ⌈ i i + 1 ⌉ = 1 \lceil{i\over{i+1}}\rceil =1 ⌈i+1i⌉=1
  • n \sqrt n n 和 n n n之间的数选 y = n y=n y=n就可以
  • n = n n n=\sqrt n \sqrt n n=n n ,多操作一下,n就能变1
  • n \sqrt n n 由 n \sqrt {\sqrt n} n 两次解决
cpp 复制代码
struct pr
{
	int x,y;
};
void solve(){
	int n;
	cin>>n;
	vector<pr>ans;
	while (n>2)
	{
		int q=ceil(sqrt(n));
		forr(i,q+1,n-1)ans.push_back({i,i+1});
		ans.push_back({n,q});
		ans.push_back({n,q});
		n=q;
	}
	cout<<ans.size()<<endl;
	for(auto i:ans){
		cout<<i.x<<' '<<i.y<<endl;
	}
}
相关推荐
我变成萤火虫12 小时前
河南萌新联赛2026第(四)场:南阳理工学院
数据结构·c++·算法·贪心算法·stl·动态规划
To_OC14 小时前
LC 239 滑动窗口最大值:从暴力超时到单调队列一遍过
javascript·算法·leetcode
.道阻且长.15 小时前
9.LeetCode算法习题讲解--滑动窗口--无重复字符的最长字串
算法·leetcode·职场和发展·哈希算法
Shaoxi Zhang16 小时前
JAVA学习笔记035——对象和JSON格式
java·笔记·学习
陈皮波比茶16 小时前
Redis学习
数据库·redis·学习
余额瞒着我当琳16 小时前
C++--深拷贝三件套 + swap + 写时拷贝 + vector 扩容 + reserve
java·开发语言·c++
ltl16 小时前
HNSW:图索引如何击败树索引
算法
ShineWinsu17 小时前
对于C++:布隆过滤器(bloomfilter)的详细解析
c++·面试·位图·位运算·布隆过滤器·海量数据·比特位
曹牧18 小时前
C#:数字的定义和表示方式
算法·c#
minglie118 小时前
espidf的esp32版的webClient
学习