首页 > 其他分享 >[赛记] csp-s模拟10

[赛记] csp-s模拟10

时间:2024-10-10 16:24:24浏览次数:1  
标签:10 赛记 int siz long find fa include csp

欧几里得的噩梦 -pts

看见是个线性基的题就没打;

其实也不是线性基,只不过模拟了一下它的过程;

考虑插入一位数时它能不能被表示,其实就是它异或上线性基中的某些值后可不可以为 $ 0 $,那么我们就可以将插入的单独一位数与 $ 0 $ 连边,将两位数互相连边,这样每插入一位数时看看它与 $ 0 $ 连不连通即可,这个可以用并查集实现;

时间复杂度:$ \Theta(n \alpha(m)) $;

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
#define int long long
const int mod = 1e9 + 7;
int n, m;
int fa[500005];
int find(int x) {
	if (x != fa[x]) fa[x] = find(fa[x]);
	return fa[x];
}
int rem[500005];
int ksm(int a, int b) {
	int ans = 1;
	while(b) {
		if (b & 1) ans = ans * a % mod;
		a = a * a % mod;
		b >>= 1;
	}
	return ans;
}
namespace LB{
	void add(int id, int x, int y) {
		x = find(x);
		y = find(y);
		if (x == y) return;
		if (x < y) swap(x, y);
		if (x != 0 || y != 0) {
			fa[x] = y;
			rem[++rem[0]] = id;
		}
	}
}
using namespace LB;
signed main() {
	freopen("Euclid.in", "r", stdin);
	freopen("Euclid.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= m; i++) fa[i] = i;
	int s;
	int x, y;
	for (int i = 1; i <= n; i++) {
		cin >> s;
		if (s == 1) {
			cin >> x;
			add(i, x, 0);
		}
		if (s == 2) {
			cin >> x >> y;
			if (x < y) swap(x, y);
			add(i, x, y);
		}
	}
	cout << ksm(2, rem[0]) << ' ' << rem[0] << '\n';
	for (int i = 1; i <= rem[0]; i++) cout << rem[i] << ' ';
	return 0;
}

购物 0pts

赛时没打;

引用题解:这种题先想单个k怎么判断,找充要条件。

考虑对于一个数 $ x $ ,它的合法的 $ k $ 值范围为 $ [\lceil \frac x2 \rceil, x] $,所以我们可以找出所有数,求所有的区间的并即可;

找出所有的数复杂度是指数级的,是不行的;

所以考虑单个 $ k $,发现如果原序列存在 $ [k, 2k] $ 的数,那么这个 $ k $ 合法,否则找所有小于 $ k $ 的数之和,如果这个和大于等于 $ k $ 也合法(因为这样就保证了有落在 $ [k, 2k] $ 中的和),所以我们只需维护一个前缀和,然后将所有 $ n $ 个数和 $ n - 1 $ 个前缀和所构成的 $ [\lceil \frac x2 \rceil, x] $ 的区间求并即可;

对于区间求并,可以珂朵莉树维护(其实就是一个 set);

时间复杂度:$ \Theta(n \log n) $;

点击查看代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
int n;
long long a[500005];
long long ans;
long long w(long long a, long long b) {
	if (a % b == 0) return a / b;
	else return a / b + 1;
}
struct sss{
	mutable long long l, r;
	bool operator <(const sss &A) const {
		return l < A.l;
	}
};
set<sss> s;
void add(long long l, long long r) {
	if (s.empty()) {
		s.insert({l, r});
		return;
	}
	set<sss>::iterator it = s.lower_bound({l, 0});
	if (it == s.end()) {
		it--;
		if (it -> r < l) {
			s.insert({l, r});
			return;
		}
	}
	if (it -> l > l) it--;
	it -> l = min(it -> l, l);
	it -> r = max(it -> r, r);
	it++;
	for (set<sss>::iterator i = it; i != s.end(); i++) {
		if (i -> l > r) break;
		if (i -> r <= r) s.erase(i);
		else {
			i -> l = r + 1;
			break;
		}
	}
}
int main() {
	freopen("buy.in", "r", stdin);
	freopen("buy.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	sort(a + 1, a + 1 + n);
	for (int i = 1; i <= n; i++) {
		long long l = w(a[i], 2);
		add(l, a[i]);
	}
	long long sum = a[1];
	for (int i = 2; i <= n; i++) {
		sum += a[i];
		long long l = w(sum, 2);
		add(l, sum);
	}
	for (set<sss>::iterator it = s.begin(); it != s.end(); it++) {
		ans += (it -> r - it -> l + 1);
	}
	cout << ans;
	return 0;
}

ants 50pts

就这道题拿分了。。。

赛时用的线段树维护莫队,时间复杂度 $ \Theta(n \sqrt n \log n) \ TLE $ 了;

正解:回滚莫队;

其实这题主要的时间开销在删除上,所以考虑用只加不减的回滚莫队;

每次用并查集维护一下最长值域联通段,然后撤销一下即可;

赛时把回滚莫队复杂度记成 $ \Theta(n^{\frac53}) $ 导致没打,其实这是带修莫队的时间复杂度

时间复杂度: $ \Theta(n \sqrt n \log n) $,但是并查集常数小,所以能过;

好像还有 $ \Theta(1) $ 链表维护的做法,没写;

点击查看代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <stack>
#include <vector>
using namespace std;
int n, m;
int a[100005];
int st[505], ed[505], belog[100005];
int sq;
struct sss{
	int l, r, id;
	inline bool operator <(const sss &A) const {
		if (belog[l] != belog[A.l]) {
			return l < A.l;
		} else {
			return r < A.r;
		}
	}
}e[100005];
int fa[100005], siz[100005], ans[100005];
int find(int x) {
	if (x != fa[x]) fa[x] = find(fa[x]);
	return fa[x];
}
stack<pair<pair<bool, int>, pair<int, int> > > s;
vector<int> v;
bool vis[100005];
int ma, lans;
void add(int o, int x) {
	vis[x] = true;
	if (o == 1) s.push({{1, x}, {fa[find(x)], siz[find(x)]}});
	if (!vis[x - 1] && !vis[x + 1]) return;
	if (vis[x - 1]) {
		if (o == 1) s.push({{0, find(x - 1)}, {fa[find(x - 1)], siz[find(x - 1)]}});
		siz[find(x - 1)] += siz[find(x)];
		siz[find(x)] = 1;
		fa[find(x)] = find(x - 1);
		ma = max(ma, siz[find(x - 1)]);
	}
	if (vis[x + 1]) {
		if (o == 1) s.push({{0, find(x + 1)}, {fa[find(x + 1)], siz[find(x + 1)]}});
		siz[find(x)] += siz[find(x + 1)];
		siz[find(x + 1)] = 1;
		fa[find(x + 1)] = find(x);
		ma = max(ma, siz[find(x)]);
	}
}
int main() {
	freopen("ants.in", "r", stdin);
	freopen("ants.out", "w", stdout);
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
	}
	for (int i = 1; i <= m; i++) {
		cin >> e[i].l >> e[i].r;
		e[i].id = i;
	}
	sq = sqrt(n);
	for (int i = 1; i <= sq; i++) {
		st[i] = (i - 1) * sq + 1;
		ed[i] = i * sq;
	}
	ed[sq] = n;
	for (int i = 1; i <= sq; i++) {
		for (int j = st[i]; j <= ed[i]; j++) {
			belog[j] = i;
		}
	}
	for (int i = 1; i <= n; i++) {
		fa[i] = i;
		siz[i] = 1;
	}
	sort(e + 1, e + 1 + m);
	int l = 1;
	int r = 0;
	int ls = 0;
	for (int i = 1; i <= m; i++) {
		ma = 1;
		if (belog[e[i].l] == belog[e[i].r]) {
			v.clear();
			for (int j = e[i].l; j <= e[i].r; j++) {
				v.push_back(a[j]);
			}
			v.push_back(0x3f3f3f3f);
			sort(v.begin(), v.end());
			int an = 0, sum = 1;
			for (int j = 0; j < v.size(); j++) {
				if (v[j + 1] != v[j] + 1) {
					an = max(an, sum);
					sum = 1;
				} else {
					sum++;
				}
			}
			ans[e[i].id] = an;
			continue;
		}
		if (belog[e[i].l] != ls) {
			lans = 1;
			ls = belog[e[i].l];
			while(!s.empty()) s.pop();
			for (int j = 1; j <= n; j++) {
				fa[j] = j;
				siz[j] = 1;
				vis[j] = false;
			}
			l = ed[belog[e[i].l]];
			r = ed[belog[e[i].l]] - 1;
		}
		if (l < ed[belog[e[i].l]]) {
			while(!s.empty()) {
				pair<pair<bool, int> , pair<int, int> > p = s.top();
				s.pop();
				if (p.first.first) vis[p.first.second] = false;
				fa[p.first.second] = p.second.first;
				siz[p.first.second] = p.second.second;
			}
			l = ed[belog[e[i].l]];
		}
		while(r < e[i].r) add(0, a[++r]);
		lans = max(ma, lans);
		while(l > e[i].l) add(1, a[--l]);
		ans[e[i].id] = max(lans, ma);
	}
	for (int i = 1; i <= m; i++) {
		cout << ans[i] << '\n';
	}
	return 0;
}

标签:10,赛记,int,siz,long,find,fa,include,csp
From: https://www.cnblogs.com/PeppaEvenPig/p/18456600

相关文章

  • IEEE全球极限编程大赛10.0题目题解:给出数字N,A,B,求出A,B之间与N互质的数的和(数据范围大)
    题目题目来源第10届IEEE极限编程大赛https://www.hackerrank.com/contests/ieeextreme-challenges/challenges/inti-setsInordertomotivatehisPeruvianstudents,ateacherincludeswordsintheQuechualanguageinhismathclass.Today,hedefinedacurious......
  • 2024/10/10
    中山市选2011杀人游戏一个环上的点可以通过询问环上任意一点来确定整个环的状态,有入度的点可以通过询问它之前的点来确定。所以我们先缩点。需要统计出所有入度为\(0\)的强连通分量的个数。注意一个特殊情况,若存在一个强连通分量满足它大小为\(1\),且它连接到的点的入度都不......
  • ChatGPT国内中文版镜像网站整理合集(2024/10/10最新)
    一、GPT中文镜像站①yixiaai.com支持GPT4、4o、o1、文件上传、知识库,支持MJ绘画②chat.lify.vip支持通用全模型,支持文件读取、插件、绘画、AIPPT③AIChat支持GPT3.5/4,4o以及MJ绘画1.什么是镜像站镜像站(MirrorSite)是指通过复制原始网站内容和结构,创建的备用网站。......
  • gjoi 2024.10.9
    当天在家里躺尸看t1过不了就去睡觉了,还好没写卡场Round哦/cf怎么有人吃错了一整盒退高烧药啊/wqT1游戏升级考虑有多少\(x\in[1,n]\)满足\(b_1+\lfloor\frac{a_1}{x}\rfloor=b_2+\lfloor\frac{a_2}{x}\rfloor\),直接对下取整做整除分块即可。gjoj卡常所以开longl......
  • SCIE1000 Python and Communication
    SCIE1000Semester2,2024PythonandCommunicationAssignment1ThescenarioAnewpublicsciencemuseuminStLuciaisdevelopinganexhibit.Afeatureofthemuseumisthateachexhibititemisaccompaniedbytwoexplanations,eachwrittenforadiffe......
  • 2024.10.10 1514版
    起于《海奥华预言》的思考◆地球管理结构和参考持续更新中...... 英文地址:https://github.com/zhuyongzhe/Earth/tags中文地址:https://www.cnblogs.com/zhuyongzhe85作者:朱永哲 ---------------------------------------------------------------------------------......
  • Day3 备战CCF-CSP练习
    Day3题目描述目前在一个很大的平面房间里有\(n\)个无线路由器,每个无线路由器都固定在某个点上。任何两个无线路由器只要距离不超过\(r\)就能互相建立网络连接。除此以外,另有\(m\)个可以摆放无线路由器的位置。你可以在这些位置中选择至多\(k\)个增设新的路由器。你的......
  • 2024.10.10 总结
    A:赛时发了什么疯非要来冲这题。不妨计各种颜色的宝石为0/1。考虑记前缀和的最大值为\(S_\max\),最小值为\(S_\min\),于是总的限制为\(|S_\max-S_\min|\leqk\)。考虑反向维护这个限制,即枚举一个\(i\),然后钦定\(i\leqS_\min\leqS_\max\leqi+k\),计算对应的序列个数。然后......
  • 10月最新AI产品经理面试20个问题汇总(含面试解题技巧、注意事项)
    这题我会!这是一个包含AI产品经理问题的备考文章,本文主要讲解AI产品经理的备考注意事项、真题展示、解题技巧及高效刷题方法,相信大家看完就一定能掌握技巧并且顺利通关!一、AI产品经理面试问题展示(20道)\1.请描述一下你过去负责的一个AI产品开发项目,包括项目的目标、过程......
  • 团队练习记录10.9
    题目链接:https://qoj.ac/contest/1480这次有个强队去讲课,偶幸校队赛时第一C-CatchYouCatchMe队友写的,签到题吧?#include<bits/stdc++.h>#defineendl'\n'usingnamespacestd;typedeflonglongll;constintINF=0x3f3f3f3f;constllN=1e6+5;constllmod=1e9+......