【补题】【atcoderabc434】【codeforces1067】

前缀和

https://atcoder.jp/contests/abc434/tasks/abc434_d

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
using ll=long long;
int main(){
	vector<vector<ll>>a(2025,vector<ll>(2025,0));
	vector<vector<ll>>b(2025,vector<ll>(2025,0));
	ll n;cin>>n;
	for(int i=1;i<=n;i++){
		ll u,d,l,r;cin>>u>>d>>l>>r;
		d++;r++;
		a[u][l]++;a[u][r]--;a[d][l]--;a[d][r]++;
		b[u][l]+=i;b[u][r]-=i;b[d][l]-=i;b[d][r]+=i;
		
	}for(int i=0;i<2025;i++){
		for(int j=0;j<2025;j++){
		    if(j){a[i][j]+=a[i][j-1];
			b[i][j]+=b[i][j-1];}
		}
	}for(int i=0;i<2025;i++){
		for(int j=0;j<2025;j++){
			if(i){a[i][j]+=a[i-1][j];
				b[i][j]+=b[i-1][j];}
		}
	}
	vector<ll>bk(n+1,0);
	for(int i=1;i<=2000;i++){
		for(int j=1;j<=2000;j++){
			if(a[i][j]==0){bk[0]++;}
			else if(a[i][j]==1){bk[b[i][j]]++;}//记录是第几块
		}
	}for(int i=1;i<=n;i++){
	    cout<<bk[0]+bk[i]<<'\n';
	}
	
}

核心思想:动态规划

前缀和的计算本质上是动态规划,利用已经计算好的结果来推导新的结果。

分步证明

第一步:水平方向前缀和

执行完第一个双重循环后:

复制代码
a[i][j] = 原数组第i行中,从第0列到第j列的所有元素之和

即:a[i][j] = original[i][0] + original[i][1] + ... + original[i][j]

第二步:垂直方向前缀和

现在我们要计算从 (0,0) 到 (i,j) 的矩形区域和:

复制代码
目标:sum(0,0 → i,j) = 所有行从第0列到第j列的和之和

当执行 a[i][j] += a[i-1][j] 时:

  • 左边的 a[i][j] 是第i行从0到j列的和
  • 右边的 a[i-1][j] 是前i-1行从0到j列的总和(因为上一步已经计算了水平前缀和)

所以:

复制代码
a[i][j] = (第i行从0到j列的和) + (前i-1行从0到j列的总和)
        = 从第0行到第i行,每行从0列到j列的和之和
        = 从(0,0)到(i,j)的矩形区域和

可视化例子

假设原数组:

复制代码
1 2 3
4 5 6
7 8 9

第一步后(水平前缀和):

复制代码
1  3  6
4  9  15
7  15 24

第二步后(垂直前缀和):

复制代码
1   3   6
5   12  21  ← 1+4=5, 3+9=12, 6+15=21
12  27  45  ← 5+7=12, 12+15=27, 21+24=45

验证:a[2][2] = 45 正是原数组所有元素之和 1+2+3+4+5+6+7+8+9=45

为什么顺序很重要

如果调换两个循环的顺序(先垂直后水平),结果也是正确的,因为前缀和计算满足交换律。

这种分步计算的方法比直接四重循环更高效,时间复杂度从 O(n⁴) 降到了 O(n²)。

这是一个很好的问题!让我来解释为什么树结构要减1。

dfs

https://atcoder.jp/contests/abc434/tasks/abc434_e

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int n;cin>>n;
	vector<int>x(n),r(n);
	map<int,vector<pair<int,int>>>g;
	for(int i=0;i<n;i++){
		cin>>x[i]>>r[i];
		int xp=x[i]+r[i];
		int xr=x[i]-r[i];
		g[xr].emplace_back(xp,i);
		g[xp].emplace_back(xr,i);
		//TODO
	}set<int>vis;
	auto dfs=[&](auto rc,int c,int en)->pair<int,int>{
		vis.insert(c);//标记当前坐标已访问
		int num=1;//当前联通分量的节点数
		int is=true;
		for(auto& [d,e]:g[c]){
			if(e==en)continue;
			if(vis.count(d)){//邻接点已访问,存在环,不是树
				is=false;
			}else{
				auto[n,f]=rc(rc,d,e);
				num+=n;
				is&=f;
			}
		}return make_pair(num,is);//节点数,是否是树
	};
	int ans=0;
	for(auto& [ket,_]:g){
		if(vis.count(ket))continue;
		//对每个联通分量dfs
		auto[num,is]=dfs(dfs,ket,-1);
		//是树,不同坐标=节点-1
		//是环,不同坐标=节点
		ans+=is?num-1:num;
		//TODO
	}cout<<ans<<'\n';
}

一棵树第一个点两条边,后来多一个点一条边,所以是n-1

如果有环,先最小生成树有n-1个点,后来利用其他边来涂色这个

模拟、思维

https://codeforces.com/contest/2158/problem/D

cpp 复制代码
#include <bits/stdc++.h>
using namespace std;
vector<array<int,2>>reduce(string &s){
	int n=s.size();
	vector<array<int,2>>op;
     int p=-1;
	//寻找相邻相同
	for(int i=0;i<n-1;i++){
		if(s[i]==s[i+1])p=i;//相邻字符的位置
		//TODO
	}//无相同,严格交替
	if(p==-1){
		//前3个一定是回文
		op.push_back({0,2});
		s[0]^=1;s[1]^=1;
		p=2;//现在有两位相等
	}char va=s[p+1];//块中字符值
	int l=p,r=p+1;//【l,r】中字符相等
	//向右扩展
	while(r+1<n){
		if(s[r+1]!=va)op.push_back({l,r});//字符不同,翻转
		r++;va=s[r];//翻转后这一段都变成s【r】
	}while(l){//字符不同,翻转
		if(s[l-1]!=va)op.push_back({l,r});
		l--;va=s[l];//更新当前块的值
	}
	//全1翻转变全0
	if(va=='1')op.push_back({0,n-1});
	return op;
}
void solve(){
	int n;cin>>n;
	string s,t;cin>>s>>t;
	auto ops=reduce(s);//s转到全0
	auto opt=reduce(t);//t转到全0
	//t变全0转,将全0变t
	reverse(opt.begin(),opt.end());
	int mo=ops.size()+opt.size();
	cout<<mo<<'\n';
	//s到全0,全0到t
	for(auto &[x,y]:ops){cout<<x+1<<' '<<y+1<<'\n';
	}for(auto &[x,y]:opt){cout<<x+1<<' '<<y+1<<'\n';
	}
}
int main(){
	ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
	int t;cin>>t;
	while(t--){
		solve();
	}
}
相关推荐
倒头就睡的小比特4 天前
算法竞赛C++常用的STL
c++·算法
小羊没烦恼!4 天前
初探性能优化——2个月到4小时的性能提升
java·开发语言·windows·算法·c#
猎头南楼4 天前
知识社区推荐系统实践:新用户冷启动与长短期兴趣建模的挑战 资深推荐算法工程师
人工智能·深度学习·算法·机器学习
旖旎夜光4 天前
力控面试题 01.01: 判定字符是否唯一(位运算) —— 题解
c++·学习·算法·leetcode·力控
wzdark4 天前
大规模并行计算中的负载均衡算法研究4
算法
Because_of_Her14 天前
并查集-听课笔记
笔记·算法·并查集
码流子4 天前
高速公路安全监测实践:碰撞监测预警+物联网底座,从感知到处置的闭环
大数据·人工智能·物联网·算法·架构
another heaven4 天前
【算法/C++ MD5算法能否逆解码?原理、C++实现与同类哈希算法对比】
c++·算法·哈希算法
wzdark4 天前
从算法设计模式看编程思维的抽象能力4
算法
2601_962218614 天前
万象生鲜系统称重自动多退少补算法解决生鲜非标品痛点
大数据·数据库·人工智能·python·算法