当前位置: 首页 > news >正文

2022.10.1模拟赛

  FSYo Orz orz orz orz %%%%%

国庆节限定模拟赛

A

100pts O ( n log ⁡ n ) O(n\log n) O(nlogn)

  二维偏序升级版,不等式变形一下,分 4 4 4 种情况讨论:

  1. a j = 0 a_j = 0 aj=0,那么 a i > 0 a_i > 0 ai>0,贡献就是所有大于 0 0 0 的数的个数
  2. a j = 1 a_j = 1 aj=1,那么 a i < a i + 1 a_i < a_i + 1 ai<ai+1,贡献就是前面所有数的个数
  3. a j ≥ 2 a_j \ge 2 aj2,那么 a i < a j a j − 1 a_i < \frac{a_j}{a_j - 1} ai<aj1aj,然后树状数组数数就可以了
  4. a j < 0 a_j < 0 aj<0,那么 a i > a j a j − 1 a_i > \frac{a_j}{a_j - 1} ai>aj1aj,和上一种情况一样了
namespace gene {
	int c[MAXN << 2] = { 0 };
	inline int lowbit(int x) { return x & -x; }
	void add(int x, int val) { for(; x <= 2 * n; x += lowbit(x)) c[x] += val; }
	int query(int x) {
		int ans = 0;
		for(; x; x -= lowbit(x)) ans += c[x];
		return ans;
	}
	double ori[MAXN << 1], de[MAXN << 1];
	void solve() {
		int ans = 0;
		for(int i = 1; i <= n; i++)
			de[i] = ori[i] = a[i], de[i + n] = ori[i + n] = 1.0 * a[i] / (a[i] - 1);
		sort(de + 1, de + 2 * n + 1);
		int m = unique(de + 1, de + 2 * n + 1) - de - 1;
		double mx = de[m]; int dmx = lower_bound(de + 1, de + m + 1, mx) - de;
		for(int j = 1; j <= n; j++) {
			int dai = lower_bound(de + 1, de + m + 1, ori[j]) - de;
			int dfr = lower_bound(de + 1, de + m + 1, ori[j + n]) - de;
			if(a[j] == 0) {
				int dze = lower_bound(de + 1, de + m + 1, 0) - de; ans += query(dmx) - query(dze); }
			else if(a[j] == 1) ans += j - 1;
			else if(a[j] >= 2) ans += query(dfr - 1);
			else ans += query(dmx) - query(dfr);
			add(dai, 1); 
		}
		cout << ans << '\n';
	}
}

100pts O ( n ) O(n) O(n)

  把式子化简一下 ( a i − 1 ) ( a j − 1 ) < 1 (a_i - 1)(a_j - 1) < 1 (ai1)(aj1)<1,于是就变成了几种情况:

  1. a j − 1 = 0 a_j - 1 = 0 aj1=0,贡献前面的所有数
  2. a j − 1 < 0 a_j - 1 < 0 aj1<0,贡献前面所有满足 a i − 1 ≥ 0 a_i - 1 \geq 0 ai10 的数
  3. a j − 1 > 0 a_j - 1 > 0 aj1>0,贡献前面所有满足 a i − 1 ≤ 0 a_i - 1 \leq 0 ai10 的数

B

10 pts

  直接暴搜,没什么好说的。

namespace sub1{
	int res = 0, m = 0;
	int pos[MAXN] = { 0 };
	int vis[MAXN] = { 0 };
	void de(){
		for(int i = 1; i <= n; i++) b[i] = ranges[i].l, b[i + n] = ranges[i].r;
		sort(b + 1, b + 2 * n + 1); m = unique(b + 1, b + 2 * n + 1) - b - 1;
	}
	int cal(){
		memset(c, 0, sizeof c);
		for(int i = 1; i <= n; i++){
			int dl = lower_bound(b + 1, b + m + 1, ranges[pos[i]].l) - b;
			int dr = lower_bound(b + 1, b + m + 1, ranges[pos[i]].r) - b;
//			printf("l = %d r = %d\n", dl, dr);
			for(int j = dl; j <= dr; j++) a[j] = i;
		} int ans = 0;
// 		for(int i = 1; i <= 2 * n; i++) cout << a[i] << ' '; puts("");
		for(int i = 1; i <= m; i++) if(!c[a[i]]) ans++, c[a[i]] = 1;
		return ans;
	}
	void dfs(int now){
		if(now == n + 1) { res = max(res, cal()); return; }
		for(int i = 1; i <= n; i++){
			if(vis[i]) continue;
			vis[i] = 1, pos[now] = i;
			dfs(now + 1);
			vis[i] = 0, pos[now] = 0;
		}
	}
	void solve(){
		de(); dfs(1);
		cout << res << '\n';
	}
}

30 pts

  可以退火(大概

  某机房大佬打的爬山,似乎比退火还更优一些,有一次爬了 50 p t s 50pts 50pts 出来,但不是很理解为什么可以排山,难道是单峰的?

namespace sub2{
	#define ESP 1e-17
	const double T0 = 1e8, MAX_TIME = 1.95 * CLOCKS_PER_SEC, dT = 0.99244353;
	int res = 0, m = 0;
	int pos[MAXN] = { 0 };
	void de(){
		for(int i = 1; i <= n; i++) b[i] = ranges[i].l, b[i + n] = ranges[i].r;
		sort(b + 1, b + 2 * n + 1); m = unique(b + 1, b + 2 * n + 1) - b - 1;
	}
	int cal(){
		memset(c, 0, sizeof c);
		for(int i = 1; i <= n; i++){
			int dl = lower_bound(b + 1, b + m + 1, ranges[pos[i]].l) - b;
			int dr = lower_bound(b + 1, b + m + 1, ranges[pos[i]].r) - b;
//			printf("l = %d r = %d\n", dl, dr);
			for(int j = dl; j <= dr; j++) a[j] = i;
		} int ans = 0;
// 		for(int i = 1; i <= 2 * n; i++) cout << a[i] << ' '; puts("");
		for(int i = 1; i <= m; i++) if(!c[a[i]]) ans++, c[a[i]] = 1;
		return ans;
	}
	void SA(){
		srand(time(0) + clock());
		double T = T0; int nowans = res;
		while(T > ESP){
			int xx = rand() % n + 1, yy = rand() % n + 1;
			swap(pos[xx], pos[yy]);
			int temp = cal();
			if(temp > nowans) nowans = temp;
			else if(exp(1.0 * (temp - nowans) / T) * RAND_MAX < rand()) swap(pos[xx], pos[yy]);
			T *= dT;
		}
//		printf("nowans = %d\n", nowans);
		res = max(res, nowans);
	}
	void solve(){
		de();
		for(int i = 1; i <= n; i++) pos[i] = i;
		res = cal();
//		printf("res = %d\n", res);
		while(clock() < MAX_TIME) SA();
		cout << res << '\n';
	}
}

100 pts

  区间 d p dp dp,把区间段点离散化,显然不影响答案。然后记录 f l , r f_{l, r} fl,r 为第 l l l 个端点到第 r r r 个端点的颜色最大值,然后就区间 d p dp dp 传统艺能,枚举中间点 k k k,并且考虑 [ k , k + 1 ] [k, k + 1] [k,k+1] 涂上了某一个颜色,然后显然这样就必须满足 ∃ \exist 区间 [ l i , r i ] [l_i, r_i] [li,ri] 使得 l ≤ l i ≤ k ≤ r i ≤ r l \le l_i \le k \le r_i \le r llikrir,如果有这样的区间我们就可以这样转移:

f l , k + f k + 1 , r + 1 → f l , r f_{l, k} + f_{k + 1, r} + 1 \to f_{l, r} fl,k+fk+1,r+1fl,r

  那么现在考虑怎么做到这个限制条件,这个地方 s t d std std 就做的很巧妙了,记录一个 s i z l , r siz_{l, r} sizl,r 表示 [ l , r ] [l, r] [l,r] 里面有多少个被完全包含的区间,这个玩意儿也可以用区间 d p dp dp 弄出来,也就是容斥一下:

s i z l , r    +=    s i z l + 1 , r + s i z l , r − 1 − s i z l + 1 , r − 1 siz_{l, r} \; \text{+=} \; siz_{l + 1, r} + siz_{l, r - 1} - siz_{l + 1, r - 1} sizl,r+=sizl+1,r+sizl,r1sizl+1,r1

  然后对于一个 k k k,如果有 s i z l , k + s i z k + 1 , r < s i z l , r siz_{l, k} + siz_{k +1, r} < siz_{l, r} sizl,k+sizk+1,r<sizl,r,那么就说明存在满足上述条件的区间,然后就是愉快的转移了。

namespace sub3DP{
	int m = 0;
	int s[MAXN][MAXN] = { 0 };
	int f[MAXN][MAXN] = { 0 };
	void de(){
		for(int i = 1; i <= n; i++) b[i] = ranges[i].l, b[i + n] = ranges[i].r;
		sort(b + 1, b + 2 * n + 1); m = unique(b + 1, b + 2 * n + 1) - b - 1;
	}
	void solve(){
		de();
		for(int i = 1; i <= n; i++){
			ranges[i].l = lower_bound(b + 1, b + m + 1, ranges[i].l) - b;
			ranges[i].r = lower_bound(b + 1, b + m + 1, ranges[i].r) - b;
			s[ranges[i].l][ranges[i].r]++;
		}
		for(int len = 1; len <= m; len++)
			for(int l = 1; len + l - 1 <= m; l++){
				int r = len + l - 1;
				s[l][r] += s[l + 1][r] + s[l][r - 1] - s[l + 1][r - 1];
			}
		for(int len = 1; len <= m; len++)
			for(int l = 1; len + l - 1 <= m; l++){
				int r = len + l - 1;
				for(int k = l; k < r; k++) if(s[l][k] + s[k + 1][r] < s[l][r])
					f[l][r] = max(f[l][r], f[l][k] + f[k + 1][r] + 1);
			}
		cout << f[1][m] << '\n';
	}
}

C

114514

10 pts

  字符串就是 a + a + c + d + a + c a + a + c + d + a + c a+a+c+d+a+c,所以显然可以枚举 a a a,枚举 c c c,枚举 d d d,然后再枚举所有子串,于是就有了一个 O ( n 6 ) O(n^6) O(n6) 的神器算法:

namespace sub1{
	int cal(string num){                                                          // num = a + a + c + d + a + c  
		/* num : a : [0 ~ (len1 - 1)], 
	         a : [len1 ~ (2len1 - 1)],
	         c : [2len1 ~ (2len1 + len2 - 1)], 
			 d : [(2len1 + len2) ~ (2len1 + len2 + len3 - 1)], 
			 a : [(2len1 + len2 + len3) ~ (3len1 + len2 + len3 - 1)], 
			 c : [(3len1 + len2 + len3) ~ (3len1 + 2len2 + len3 - 1)]
		*/ 
		int n = num.size(), ans = 0;
		if(n < 6) return 0;
		for(int len1 = 1; len1 < n; len1++){                                      // 枚举 a 的长度 
	//		printf("len1 = %d\n", len1); 
			string a;
			for(int i = 0; i < len1; i++) a += num[i];
			for(int len2 = 1; 2 * len1 + len2 < n; len2++){                       // 枚举 c 的长度 
				string c;
				for(int i = 2 * len1; i < 2 * len1 + len2; i++) c += num[i];
				for(int len3 = 1; 2 * len1 + len2 + len3 < n; len3++){            // 枚举 d 的长度 
					string d;
					for(int i = 2 * len1 + len2; i < 2 * len1 + len2 + len3; i++) d += num[i];
					string pat = a + a + c + d + a + c; bool f = 1;
					for(int i = 0; i < n; i++) if(num[i] != pat[i]) f = 0;
					if(pat.size() != n) f = 0;
	//				cout << "  pat = " << pat << '\n';
	//				cout << "  a = " << a << '\n' << "  c = " << c << '\n' << "  d = " << d << '\n'; puts("");
					if(f) ans++;
				}
			}
		}
		return ans;
	}
	void solve(){
		int n = pp.size(), ans = 0;
		for(int i = 0; i < n; i++)
			for(int j = 0; j < i; j++){
				string temp;
				for(int k = j; k <= i; k++) temp += pp[k];
				ans += cal(temp);
			}
		cout << ans << '\n';
	}
} 

60 pts

  就是在 O ( n 6 ) O(n^6) O(n6) 的基础上优化了一下,就不枚举 d d d 了,然后弄了一个 h a s h hash hash 搞到了 O ( n 4 ) O(n^4) O(n4),然后就有 60 p t s 60 pts 60pts 了。

namespace sub2{
	const int base = 13331;
	ull pw[MAXN] = { 0 };
	ull hs[MAXN] = { 0 };
	inline ull get(int l, int r) { return hs[r] - hs[l - 1] * pw[r - l + 1]; }
	inline bool equal(int s1, int s2, int l) { return get(s1, s1 + l - 1) == get(s2, s2 + l - 1); }
	inline bool check(int l, int r, int len1, int len2){
		if(!equal(l, l + len1, len1)) return false;
		if(!equal(l, r - len2 - len1 + 1, len1)) return false;
		if(!equal(l + 2 * len1, r - len2 + 1, len2)) return false;
		return true;
	}
	void solve(){
		int ans = 0; pw[0] = 1;
		for(int i = 1; i <= len; i++)
			hs[i] = hs[i - 1] * base + pp[i - 1], pw[i] = pw[i - 1] * base;
		for(int l = 1; l <= len; l++)
			for(int r = l; r <= len; r++){
				int mx1 = (r - l + 1) / 3;
				for(int len1 = 1; len1 <= mx1; len1++){                                 // 枚举 a 的长度 
					int mx2 = (r - l + 2 - 3 * len1) >> 1;
					for(int len2 = 1; len2 < mx2; len2++)                               // 枚举 c 的长度 
						if(check(l, r, len1, len2)) ans++;
				}
			}
		cout << ans << '\n';
	}
}

100 pts

D

相关文章:

  • 西瓜书研读——第三章 线性模型: 线性判别分析 LDA
  • 云计算概论 --云安全机制
  • java计算机毕业设计企业公开招聘系统源程序+mysql+系统+lw文档+远程调试
  • 谷粒学院16万字笔记+1600张配图(十五)——微信扫码登录
  • 详述进程概念【Linux】
  • VVC系列(一)VTM下载编译
  • LeetCode50天刷题计划第二季(Day 7 — 验证二叉搜索树(15.00-16.00
  • 在 IDEA 中用 Nacos2.1.0 源码启动集群模式并调试
  • 前端毕业设计:Nodejs+Vue菜鸟驿站仓库管理系统的设计与实现
  • 服务器的基本概念与初识Ajax,jQuery当中的ajax,get(),post()接口,postman测试接口
  • Java基于SpringBoot+Vue+nodejs的企业公司人事管理系统 Element
  • webpack5构建基于Vue3+ElementPlus项目搭建(开发和生产)
  • 6. 测度论-期望及其性质
  • java计算机毕业设计贫困助学管理系统源程序+mysql+系统+lw文档+远程调试
  • Java | 异常类【万字详解,看过来】
  • android 一些 utils
  • CSS3 变换
  • C语言笔记(第一章:C语言编程)
  • JavaScript 基础知识 - 入门篇(一)
  • JAVA之继承和多态
  • JS题目及答案整理
  • Python连接Oracle
  • Terraform入门 - 1. 安装Terraform
  • Vue源码解析(二)Vue的双向绑定讲解及实现
  • webpack入门学习手记(二)
  • 名企6年Java程序员的工作总结,写给在迷茫中的你!
  • 三分钟教你同步 Visual Studio Code 设置
  • 提升用户体验的利器——使用Vue-Occupy实现占位效果
  • 学习笔记DL002:AI、机器学习、表示学习、深度学习,第一次大衰退
  • Linux权限管理(week1_day5)--技术流ken
  • 如何在 Intellij IDEA 更高效地将应用部署到容器服务 Kubernetes ...
  • ​​​​​​​sokit v1.3抓手机应用socket数据包: Socket是传输控制层协议,WebSocket是应用层协议。
  • ​中南建设2022年半年报“韧”字当头,经营性现金流持续为正​
  • #常见电池型号介绍 常见电池尺寸是多少【详解】
  • #预处理和函数的对比以及条件编译
  • (Redis使用系列) Springboot 使用redis实现接口幂等性拦截 十一
  • (二)linux使用docker容器运行mysql
  • (汇总)os模块以及shutil模块对文件的操作
  • (七)理解angular中的module和injector,即依赖注入
  • (原创)boost.property_tree解析xml的帮助类以及中文解析问题的解决
  • (转贴)用VML开发工作流设计器 UCML.NET工作流管理系统
  • ****** 二 ******、软设笔记【数据结构】-KMP算法、树、二叉树
  • .dwp和.webpart的区别
  • .NET CORE 2.0发布后没有 VIEWS视图页面文件
  • .net core 客户端缓存、服务器端响应缓存、服务器内存缓存
  • .NET Core工程编译事件$(TargetDir)变量为空引发的思考
  • .NET Remoting Basic(10)-创建不同宿主的客户端与服务器端
  • .NET 解决重复提交问题
  • .NetCore Flurl.Http 升级到4.0后 https 无法建立SSL连接
  • .NetCore 如何动态路由
  • @html.ActionLink的几种参数格式
  • @media screen 针对不同移动设备
  • [ vulhub漏洞复现篇 ] Django SQL注入漏洞复现 CVE-2021-35042
  • [ 云计算 | AWS 实践 ] Java 如何重命名 Amazon S3 中的文件和文件夹
  • [ 云计算 | AWS 实践 ] 基于 Amazon S3 协议搭建个人云存储服务