首页 > 其他分享 >ABC211 复盘

ABC211 复盘

时间:2024-04-17 18:34:59浏览次数:24  
标签:ABC211 val int yy ++ xx que 复盘

ABC211 复盘

[ABC211C] chokudai

思路解析

题目说的很明白,看到匹配子序列可以轻易想到是简单 dp,直接做即可。

时间复杂度:两个字符串两层循环,\(O(8 \times N)\)。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
const long long mod = 1e9 + 7;
string t = " chokudai";
string s;
long long f[15];
int main() {
	cin >> s;
	s = ' ' + s;
	f[0] = 1;
	for(int i = 1; i < s.size(); i++) {
		for(int j = 1; j <= 8; j++) {
			if(s[i] == t[j]) {
				f[j] = (f[j] + f[j - 1]) % mod;
			}
		}
	}
	cout << f[8];
	return 0;
}

[ABC211D] Number of Shortest paths

思路解析

题目其实说得很明白了,就是最短路计数。我们可以用一个 \(s_i\) 表示从起点到 \(i\) 的最短路计数,然后进行 bfs,由于边权为 \(1\),所以可以使用 bfs 求最短路。如果 \(u \to v\) 是 \(v\) 的最短路的其中一段,就把 \(s_u \to s_v\) 转移即可。

注意要记得取模。

时间复杂度:bfs,复杂度 \(O(N)\)。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 2e5 + 10, mod = 1e9 + 7;
int n, m, d[N], s[N];
vector<int> g[N];
void bfs() {
	memset(d, 0x3f, sizeof(d));
	d[1] = 0; s[1] = 1;
	queue<int> q;
	q.push(1);
	while(!q.empty()) {
		int u = q.front(); q.pop();
		for(auto it : g[u]) {
			if(d[it] >= d[u] + 1) {
				if(d[it] > 1e8) q.push(it);
				d[it] = d[u] + 1;
				s[it] = (s[it] + s[u]) % mod;
			}
		}
	}
}
int main() {
	cin >> n >> m;
	for(int i = 1, u, v; i <= m; i++) {
		cin >> u >> v;
		g[u].push_back(v);
		g[v].push_back(u);
	}
	bfs();
	cout << s[n];
	return 0;
}

[ABC211E] Red Polyomino

思路解析

可见直接枚举每个格子是否着色会 TLE,于是可以想到 dfs,dfs(x) 表示我们已经用了 \(x\) 个红色方格,然后只找周围又红色格子的白格子转移,然后只要在每一个 dfs 里只进行一次递归后就返回,就可以避免 TLE 和重复方案。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 10;
int n, k, ans = 0;
char ch[N][N];
int dx[4] = {0, 0, -1, 1};
int dy[4] = {-1, 1, 0, 0};
bool check(int x, int y) {
	return (x > 0 && x <= n && y > 0 && y <= n);
}
void dfs(int c) {
	if(c == k) return (void)(ans++);
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			if(ch[i][j] == '.') {
				bool flag = false;
				for(int d = 0; d < 4; d++) {
					int nx = i + dx[d], ny = j + dy[d];
					flag |= (check(nx, ny) && (ch[nx][ny] == '@'));
				}
				if(flag || c == 0) {
					ch[i][j] = '@'; dfs(c + 1);
					ch[i][j] = '#'; dfs(c);
					ch[i][j] = '.';
					return;
				}
			}
		}
	}
}
int main() {
	cin >> n >> k;
	for(int i = 1; i <= n; i++) {
		for(int j = 1; j <= n; j++) {
			cin >> ch[i][j];
		}
	}
	dfs(0);
	cout << ans;
	return 0;
}

[ABC211F] Rectilinear Polygons

思路解析

先说结论:扫描线。顾名思义,扫描线的本质就是用一条线沿着 \(x\) 或 \(y\) 轴扫过去,每碰到一条边就记录一下加边后是面积是增加还是减少,然后用树状数组或线段树统计。由于我们并不需要知道整张图所有的位置的值,我们就只需要求出来扫描线所在的那一行 or 列每一个点的值即可。

这里就不过多解释,如果没有学过扫描线建议去做一下模板题 ,推荐看第一篇题解。

接下来就是本题的重点,该如何把不规则图形存下来。如下图,我们先把图上的竖边找出来,同时给点的顺序标一个号。

可见四条边中左边三条的权值都是增加的,只有右边一条是减少的。我们寻找边上的两点和权值的关系,可以发现,由于是点顺序输入的,所以每一条正边权的边的两点中编号较小的点 \(y\) 值也是更小的,而每一条边的两点中编号较小的点的编号一定是奇数。因此我们可以给每一条边都判断两点编号的大小来决定是用正边权还是负边权。

实现

我们根据以上所说的方式存好每一条边,然后将边按 \(x\) 的值排序,满足扫描线的性质。对于询问我们将询问离线下来,同样按 \(x\) 排序,这样我们在进行加边之前判断当前扫描线是否已经处理了所有 \(x\) 小于当前询问的 \(x\) 的边,若已经处理完就更新答案。

接下来有几点注意事项。

  • 题目中的输入点的顺序不一定满足我们想要的输入顺序,所以我们需要自己找到一个在 \(x\) 最小的情况下 \(y\) 也最小的点做编号为 \(1\) 的点。
  • 由于我们只需要知道一个点被覆盖的次数,所以可以将模板中的线段树换成树状数组区修单查。
  • 由于我们需要先把当前 \(x\) 轴上的边加完再统计询问,所以我们要在所有边的最后加上一个 \(x=\inf,val=0\) 的边,这样就能防止最后有几个点没有处理到。

code

#include<bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10, M = 1e5;
int n, m, xx[N], yy[N], tv[N], q, c[N], ans[N];
struct side {
	int x, ya, yb, val;
};
struct point {
	int x, ya, yb; 
};
struct query {
	int x, y, p;
};
void add(int x, int y) {
	for(; x <= M; x += (x & -x)) {
		c[x] += y;
	}
}
int ask(int x) {
	int sum = 0;
	for(; x > 0; x -= (x & -x)) {
		sum += c[x];
	}
	return sum;
}
int main() {
	cin >> n;
	vector<side> v;
	for(int i = 1; i <= n; i++) {
		cin >> m;
		for(int i = 0; i < m; i++) {
			cin >> xx[i] >> yy[i];
			xx[i]++; yy[i]++;
		}
		int p = 0;
		for(int i = 0; i < m; i++) {
			if(xx[i] == xx[p] && yy[i] < yy[p]) p = i;	//找到起始点,注意 y 轴也要判
			else if(xx[i] < xx[p]) p = i;
		}
		int val = 1;
		for(int i = 0; i < m; i++) {
			int w = (i + p) % m;
			tv[w] = val;	//给点加权
			val = -val;
		}
		for(int i = 0; i < m; i += 2) {	//判断
			if(yy[i] < yy[i + 1]) v.push_back({xx[i], yy[i], yy[i + 1], tv[i]});
			else v.push_back({xx[i], yy[i + 1], yy[i], tv[i + 1]});
		}
	}
	sort(v.begin(), v.end(), [](side x, side y) {	//按 x 排序
		if(x.x != y.x) return x.x < y.x;
		else return x.ya < y.ya;
	});
	v.push_back({M + 1, 1, 1, 0});	//避免结尾有点没判
	vector<query> que;
	cin >> q;
	for(int i = 1; i <= q; i++) {
		cin >> xx[i] >> yy[i];
		xx[i]++; yy[i]++;
		que.push_back({xx[i], yy[i], i});	//离线
	}
	sort(que.begin(), que.end(), [](query x, query y) {	//排序
		if(x.x != y.x) return x.x < y.x;
		else return x.y < y.y;
	});
	int pos = 0;
	for(auto it : v) {
		int x = it.x, ya = it.ya, yb = it.yb, val = it.val;
		for(; que[pos].x < x && pos < (int)que.size(); pos++) {
			ans[que[pos].p] = ask(que[pos].y);	//若已经操作完则更新
		}
		add(ya, val); add(yb, -val);	//加权
	}
	for(int i = 1; i <= q; i++) cout << ans[i] << '\n';
	return 0;
}

标签:ABC211,val,int,yy,++,xx,que,复盘
From: https://www.cnblogs.com/2020luke/p/18141461

相关文章

  • vue3复盘学习(一)
    其实说是复盘,因为在平常的开发中因为公司一些项目和其他原因断断续续的使用了一段时间vue3,因为着急赶项目,有些知识点没有系统性学习,所以决定从今天开始一点点再学习一遍٩(•̤̀ᵕ•̤́๑)ᵒᵏᵎᵎᵎᵎ哈哈!刚开始从vue2过渡到vue3的同学们其实是有些不适应的,但是随着前端框......
  • 面试复盘
    2024.02投了微软的暑期实习,3.25的时候收到了拒信,没有一个明确的反馈,总之noselected。猜测是因为:1.背景挂背景确实算不上很好2.技术挂这点可能性比较大,因为大学这几年除了学算法写大作业,在技术层面没有钻研得很深入。感觉微软和google这样的公司在招人少的情况下,会偏好有开......
  • ABC 223 复盘
    ABC223复盘[ABC223C]Doukasen思路解析根据题目可知,燃烧的总时长肯定不变,所以我们可以直接从头开始遍历找到第一根香使得烧完这根香后的时间会大于总时长的一半,然后加上剩余时间下会烧掉的长度即可。时间复杂度:一次遍历,\(O(N)\)。code#include<bits/stdc++.h>usingnames......
  • [ABC211F] Rectilinear Polygons 题解
    [ABC211F]RectilinearPolygons题解思路什么的上一篇题解已经写的非常明白了,这里只是提供一个补充&另一个实现的方法。思路解析先说结论:扫描线。顾名思义,扫描线的本质就是用一条线沿着\(x\)或\(y\)轴扫过去,每碰到一条边就记录一下加边后是面积是增加还是减少,然后用树状......
  • [ABC211D] Number of Shortest paths 题解
    [ABC211D]NumberofShortestpaths题解思路解析题目其实说得很明白了,就是最短路计数。我们可以用一个\(s_i\)表示从起点到\(i\)的最短路计数,然后进行bfs,由于边权为\(1\),所以可以使用bfs求最短路。如果\(u\tov\)是\(v\)的最短路的其中一段,就把\(s_u\tos_v\)......
  • ABC221 复盘
    ABC221复盘[ABC221A]Seismicmagnitudescales思路解析数据范围\(B\leA\le10\),可以发现能直接暴力求解。注意开longlong。code//ABC221A#include<bits/stdc++.h>usingnamespacestd;inta,b;intmain(){ cin>>a>>b; a-=b; longlongans=1; for......
  • Java后端新手的第一次面试复盘
    昨天经历了第一次Java后端实习生面试,在无数次的简历投递后,很难得的一次面试机会,收获很多,也深刻感受到自己能力的不足(还需要继续沉淀半个学期),在此记录下收获和感悟,如有错误,欢迎指正!1.面试流程闲聊(5分钟):自我介绍+询问背景动机技术问答(45分钟):包括Java基础、数据库技......
  • 转盘小程序首页运营复盘记录
    转盘小程序首页运营复盘记录~今天是4月1号,距离我的转盘小程序上线也一月有余了正如大家期待的那样,是的,我的转盘小程序已经在3月份正式上线发布了,具体的时间线如下所示  *2024-03-30功能完善,增加敏感词过滤*2024-03-25功能完善,支持语音播报*2024-03-20功能完善,新增......
  • Kaggle量化比赛复盘: Optiver - Trading at the Close
    目录前言一、开源方案1.6th获奖方案(代码未开源)1.1.特征工程(关键代码)1.2.方案解析2. 7th获奖方案(开源)2.1.特征工程2.2.特征工程3. 9th获奖方案(半开源)3.1.特征构造3.2.特征筛选3.3.模型3.4.zero_sum(标签后处理)4. 14th获奖方案(开源)4.1.方案......
  • BUPT 2024 Spring Training #3(ICPC2023 杭州站)Ag复盘
    D-OperatorPrecedence求一个长度为\(2n\)的序列\(a_{2n}\)满足条件\((a_1×a_2)+(a_3×a_4)+\ldots+(a_{2n-1}×a_{2n})=a_1×(a_2+a_3)×\ldots×(a_{2n-2}+a_{2n-1})×a_{2n}\)solution构造题显然找特殊规律。考虑到乘法构造难度大于加法,可以从乘法开始考虑。......