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

[赛记] csp-s模拟2

时间:2024-09-18 12:26:00浏览次数:9  
标签:赛记 return int mid long cin include csp 模拟

不相邻集合 64pts

赛时打的用 $ set $ 打的假做法A了,但是没敢交,整了个暴力64pts;

可以发现,对于给定的一个序列,我们只需研究每个数一次就行,因为如果一个数出现多次,答案是不变的;

我们又可以发现,对于一个连续段(比如 1 2 3 4 5 ,其答案最多为 $ \lceil \frac n2 \rceil $ ,其中 $ n $ 为此连续段的长度),所以我们只需动态维护极长连续段的长度即可;

用并查集可以很好维护,每次新加进来一个数的时候分类讨论即可;

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

点击查看代码
#include <iostream>
#include <cstdio>
using namespace std;
int n;
int a[500005];
bool vis[500005];
int fa[500005], siz[500005];
int find(int x) {
	if (x != fa[x]) fa[x] = find(fa[x]);
	return fa[x];
}
int w(int x, int y) {
	if (x % y == 0) return x / y;
	else return x / y + 1;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> n;
	int ma = -1;
	for (int i = 1; i <= n; i++) {
		cin >> a[i];
		ma = max(ma, a[i]);
	}
	for (int i = 1; i <= ma; i++) {
		fa[i] = i;
		siz[i] = 1;
	}
	int ans = 1;
	cout << 1 << ' ';
	vis[a[1]] = true;
	for (int i = 2; i <= n; i++) {
		if (vis[a[i]]) {
			cout << ans << ' ';
			continue;
		}
		vis[a[i]] = true;
		if (!vis[a[i] - 1] && !vis[a[i] + 1]) {
			ans++;
		}
		if (!vis[a[i] - 1] && vis[a[i] + 1]) {
			int x = find(a[i]);
			int y = find(a[i] + 1);
			ans -= w(siz[y], 2);
			fa[x] = y;
			siz[y] += siz[x];
			ans += w(siz[y], 2);
		}
		if (vis[a[i] - 1] && !vis[a[i] + 1]) {
			int x = find(a[i]);
			int y = find(a[i] - 1);
			ans -= w(siz[y], 2);
			fa[x] = y;
			siz[y] += siz[x];
			ans += w(siz[y], 2);
		}
		if (vis[a[i] - 1] && vis[a[i] + 1]) {
			int x = find(a[i]);
			int y1 = find(a[i] - 1);
			int y2 = find(a[i] + 1);
			ans -= (w(siz[y1], 2) + w(siz[y2], 2));
			fa[x] = y1;
			siz[y1] += siz[x];
			fa[y1] = y2;
			siz[y2] += siz[y1];
			ans += w(siz[y2], 2);
		}
		cout << ans << ' ';
	}
	return 0;
}

线段树 20pts

暴力20pts;

仔细想想,我们的问题是如何快速求出一个节点的子树的标号和;

不妨设 $ f_{n, x} $ 为一棵有 $ n $ 个叶子的线段树,根的标号是 $ x $ 时的子树和是多少,那么我们不难发现,$ f_{n, x} $ 是关于 $ x $ 的一次函数,且有下列递推式:

\[ f_{n, x} = f_{\lceil \frac n2 \rceil, x << 1} + f_{\lfloor \frac n2 \rfloor, x << 1 | 1} \]

我们用一次函数的通用表达形式表达出此递推式,可得出 $ k $ 和 $ b $ 的递推式,记忆化搜索即可;

点击查看代码
#include <iostream>
#include <cstdio>
#include <map>
using namespace std;
const long long mod = 1e9 + 7;
int t;
long long n, x, y;
map<long long, long long> k;
map<long long, long long> b;
inline long long ls(long long x) {
	return x << 1;
}
inline long long rs(long long x) {
	return x << 1 | 1;
}
long long w(long long a, long long b) {
	if (a % b == 0) return a / b;
	else return a / b + 1;
}
long long K(long long x) {
	if (k[x]) return k[x];
	if (x == 0) return 0;
	return k[x] = (2 * (K(w(x, 2)) + K(x / 2) % mod) % mod + 1) % mod;
}
long long B(long long x) {
	if (b[x] || x == 1) return b[x];
	if (x == 0) return 0;
	return b[x] = (B(w(x, 2)) + B(x / 2) % mod + k[x / 2] % mod);
}
long long ask(long long id, long long L, long long R, long long l, long long r) {
	if (L >= l && R <= r) {
		return (k[R - L + 1] * (id % mod) % mod + b[R - L + 1]) % mod;
	}
	long long mid = (L + R) >> 1;
	if (r <= mid) return ask(ls(id), L, mid, l, r);
	else if (l > mid) return ask(rs(id), mid + 1, R, l, r);
	else return (ask(ls(id), L, mid, l, mid) + ask(rs(id), mid + 1, R, mid + 1, r)) % mod;
}
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> t;
	while(t--) {
		cin >> n >> x >> y;
		k.clear();
		b.clear();
		k[1] = 1;
		b[1] = 0;
		K(n);
		B(n);
		cout << ask(1, 1, n, x, y) << '\n';
	}
	return 0;
}

标签:赛记,return,int,mid,long,cin,include,csp,模拟
From: https://www.cnblogs.com/PeppaEvenPig/p/18418225

相关文章

  • [赛记] csp-s加赛1
    小W与制胡串谜题50pts这种题,就是想到+玄学;感觉刚接触OI时做过这种题,当时学得少,蒙一下就过了。现在蒙不了了,也确实可供想的方向很多,所以像这种签到题比较不好做;字符串数组是可以$sort$的,所以我们重载$cmp$为a+b<b+a即可;至于正确性,直观感觉一下确实是对的,要......
  • CSP-J/S复赛提交指南!防止爆零必读!
    文件提交模版代码:#include<bits/stdc++.h>usingnamespacestd;intmain(){//打开输入文件,输出文件freopen("test.in","r",stdin);freopen("test.out","w",stdout);//正常的逻辑代码//关闭输入文件输出文件fclose(stdin);......
  • java多线程模拟多个售票员从同一个票池售票
    程序功能这段代码模拟了多个售票员从一个有限的票池中售票的过程。主要功能如下:票池共有50张票,多个售票员(线程)并发进行售票。使用同步机制确保线程安全,避免多个售票员同时出售同一张票。每个售票员不断检查票池是否有票,有票则售出一张,直到票池中的票售完为止。代码cl......
  • CSP初赛知识点:Linux 系统
    CSP初赛知识点:Linux系统前言近年CSP初赛几乎前5道选择题都有一两道有关Linux系统的使用,所以作为备战CSP-J/S2024的资料,整理下来啦。祝各位今年所有考试都能考出自己满意的成绩!1、常用文件操作命令以下设文件名均为csp,需要复制或修改成的文件名均为rp。功能......
  • 58. 区间和(第九期模拟笔试)
    中秋节摆了一天,感觉畏难情绪一直困扰着我,要好好调制状态才行。#include<iostream>#include<vector>usingnamespacestd;intmain(){intn=0;cin>>n;vector<int>sum(n,0);for(inti=0;i<n;++i){intnum;cin>>......
  • 信息学奥赛初赛天天练-91-CSP-S2023基础题3-编译命令、树的重心、拓扑排序、进制转换
    PDF文档公众号回复关键字:202409172023CSP-S选择题1单项选择题(共15题,每题2分,共计30分:每题有且仅有一个正确选项)11以下哪个命令,能将一个名为main.cpp的C++源文件,编译并生成一个名为main的可执行文件?()Ag++-omainmain.cppBg++-omain.cppmainCg++......
  • 2024.09.17模拟赛总结
    破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了破防了$T1$怎么每次$rfy$模拟赛,$T1$都这么难。想了大半场比赛,结果还没做出来,要是换成$T2$应该能过。$T......
  • 201909-2 小明种苹果(续)ccfcsp
    一道简单的模拟。。。includeincludeusingnamespacestd;intmain(){constintN=1010;booldrop[N]={false};intn,m,i,j,cnt=0,cnt1=0;cin>>n;inty;intsum=0,sum1,temp=0;intindex;for(i=0;i<n;i++){ sum1=0;scanf("%d",&m);for(j=0;j&......
  • pta重排链表(一个很清晰的实现,完全模拟链表的实现)
    #include<iostream>#include<iomanip>#include<unordered_map>#include<string>usingnamespacestd;constintN=100010;unordered_map<string,string>neStr;unordered_map<string,int>eStr;stringheadStr;intn;......
  • 历年CSP-J初赛真题解析 | 2019年CSP-J初赛阅读程序(16-33)
    学习C++从娃娃抓起!记录下CSP-J备考学习过程中的题目,记录每一个瞬间。附上汇总贴:历年CSP-J初赛真题解析|汇总_热爱编程的通信人的博客-CSDN博客#include<cstdio>#include<cstring>usingnamespacestd;charst[100];intmain(){scanf("%s",st);intn......