10.31日模拟赛总结

文章目录

  • 考试时间及策略
  • 考试结果
  • 考试反思
  • 题解
      • A.进步科学
      • B.吉吉没急
      • C.老杰克哒
      • D.季积晓淆

考试时间及策略

没啥好说的,因为好像都不会。所以全场感觉都在罚坐,很痛苦。

考试结果

30 + 0 + 50 + 5 = 85

考试反思

T1:T1是个神奇状压,感觉确实想不到。还是记住这个技巧吧。
T2:也是一道很难的题,会不了一点。
T3:只会 50pts 贪心的,没想出来暴力DP。如果能想出来暴力DP应该能想到正解吧。
T4:好像是FTT,会不了一点。

题解

A.进步科学

在这里插入图片描述

分析:
      正常状压感觉没有什么阶段,我们设 d p i , m a s k dp_{i,mask} dpi,mask 表示第 i i i 秒所有树上的节点的状态为 m a s k mask mask 是否可行。
      然后转移我们考虑若 d p i , m a s k = 1 dp_{i, mask} = 1 dpi,mask=1,那么我们让导致这个状态的操作整体后移1s,并且枚举第一秒操作哪个节点或者不操作节点。这样的好处是第 i + 1 i + 1 i+1 秒 可以直接继承第 i i i 秒的状态,不用再考虑前 i i i 秒的操作会不会在 第 i + 1 i + 1 i+1 秒产生影响。
      我们设 j u m p i , j jump_{i, j} jumpi,j 表示如果扭动了第 i i i 个点,在扭动 j j j 秒后每个点的状态(最开始都是 0 0 0)。我们可以预处理出来 j u m p jump jump 数组,然后转移 就是如果第一秒扭动了点 u u u,那么 d p i , m a s k → d p i + 1 , m a s k ⊕ j u m p u , i dp_{i, mask} \to dp_{i+1, mask \oplus jump_{u, i} } dpi,maskdpi+1,maskjumpu,i。最后如果某一时刻询问的状态为 1 1 1 就直接输出就好了。可以想到最多 n n n 秒就一定能得到答案。

CODE:

#include<bits/stdc++.h>// 设dp[i][mask] 表示i时刻状态为mask是否可行 
using namespace std;// 我们考虑 i -> i + 1 的时候, 把操作往后平移一个单位,然后在第一时刻操作一个数。
const int N = 17;
bool dp[N][1 << 16]; 
int jump[N][N], fa[N], n, k, mask;
int main(){
	freopen("decoration.in", "r", stdin);
	freopen("decoration.out", "w", stdout); 
	scanf("%d", &n);
	for(int i = 2; i <= n; i++){
		scanf("%d", &fa[i]); 
	}
	for(int i = 1; i <= n; i++){
		scanf("%d", &k);
		if(k) mask |= (1 << (i - 1));
	}
	for(int i = 1; i <= n; i++){
		int now = i; k = 0;
		jump[i][0] = (1 << (i - 1));
		for(int j = 1; j <= n; j++){
	     	if(fa[now]) jump[i][j] = (jump[i][j - 1] | (1 << (fa[now] - 1))), now = fa[now];
	     	else jump[i][j] = jump[i][j - 1];
		}
	}
	dp[0][0] = 1;
	for(int i = 0; i <= n; i++){//最多n秒就可以了 
		for(int j = 0; j < (1 << n); j++){
			if(dp[i][j]){
				dp[i + 1][j] |= dp[i][j];//第一秒啥也不干 
				for(int k = 1; k <= n; k++){
					dp[i + 1][j ^ jump[k][i]] |= dp[i][j];  // 第一秒选择了k,剩下的平移,那么可以抵消 
				}
			}
		}
		if(dp[i][mask]){
			printf("%d\n", i);
			break;
		}
	}
	return 0;
}

B.吉吉没急

在这里插入图片描述

分析:
      很神奇的一道题。
      我们首先把最后确定没学会算法的人当成一个限制。也就是说,我们考虑通过这些人来给其他人加一个限制。
      具体来说,我们设 h i h_{i} hi 表示每个人 允许最早在什么时间学会算法。如果 x x x 最后没有学会,那么 h i = I N F h_i = INF hi=INF。我们跑一边 dijkstra ,设当前在堆头的点编号为 u u u,与它连边的点是 v v v,边的出现时间范围时 [ l , r ] [l,r] [l,r]。若 h u > r h_u > r hu>r,说明如果 v v v 这个人想要学会算法,最早得在 l + 1 l + 1 l+1 时刻,因为我们至少要拿出 1 s 1s 1s 使得这个时刻 v v v 还没学会算法, u u u 此时和他吃饭。而 l + 1 l + 1 l+1 相当与是这个限制的极限。我们将 h v h_v hv 赋值成 m a x ( h v , l + 1 ) max(h_v, l + 1) max(hv,l+1),如果更新了放入堆中。如果 h u ≤ r h_u \leq r hur,也就意味着 h u h_u hu 允许在 r r r 之前学会算法,所以 h v h_v hv 什么时候学会都无所谓,我们只需要让边在某一个合适的时刻出现就好了。
      跑完一边 dijkstra 后,我们检验一下 h 1 h_1 h1 是否大于 0 0 0。如果 h 1 h_1 h1 大于 0 0 0,那么一定无解,因为这意味着 1 1 1 号点不允许一开始就学会算法,与条件是冲突的。
      否则,我们设 d i d_i di 表示每个点在满足 h i h_i hi 的限制下(也就是 d i d_{i} di 要大于等于 h i h_i hi)最早能够什么时候学会算法。因为每一个点越早学会算法,才越有可能教会其他最后确定学会的人。开始时 d 1 = 0 d_1 = 0 d1=0,其他的点设成 I N F INF INF,最后我们只需要检验所有确定学会的人 x x x 他的 d x d_x dx 是否等于 I N F INF INF 就好了。如果有一个等于,那么无解,否则有解。
      相当于 h h h 数组用来检验能否满足让确定学不会的人能够学不会, d d d 数组用来保证确定学会的人可以学会。

CODE:

#include<bits/stdc++.h>// 首先根据不能学会算法的人求出每一个人学会算法的最早时间 
using namespace std;// 然后在大于等于这个最早时间的前提下,每个人学会算法的时间应该尽可能早,这样能保证传递给后面的人 
const int N = 2e5 + 10;
int read(){
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){if(c == '-') f = -1, c = getchar();}
	while(isdigit(c)){x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}
	return x * f;
}
struct edge{
	int v, last, l, r;
}E[N * 2];
struct state1{
	int x, val;
	bool operator < (const state1 &a)const{
		return a.val > val;
	}
};
struct state2{
	int x, val;
	bool operator < (const state2 &a)const{
		return a.val < val;
	}
};
priority_queue< state1 > q1;
priority_queue< state2 > q2; 
const int INF = 1e9;
int head[N], n, m, u, v, l, r, d[N], h[N], tot, flag[N];
void add(int u, int v, int l, int r){
	E[++tot].v = v; 
	E[tot].last = head[u];
	E[tot].l = l;
	E[tot].r = r;
	head[u] = tot;
}
bool vis[N];
void dijkstra1(){
	memset(vis, 0, sizeof vis);
	while(!q1.empty()){
		state1 u = q1.top(); q1.pop();
		int x = u.x, val = u.val;
		if(vis[x]) continue;
		vis[x] = 1;
		for(int i = head[x]; i; i = E[i].last){
			int v = E[i].v, l = E[i].l, r = E[i].r;
			if(h[x] > r){
				if(h[v] < l + 1){
					h[v] = l + 1;
					q1.push((state1){v, h[v]}); 
				}
			}
		}
	}
}
void dijkstra2(){
	memset(vis, 0, sizeof vis);
	while(!q2.empty()){
		state2 u = q2.top(); q2.pop();
		int x = u.x, val = u.val;
		if(vis[x]) continue;
		vis[x] = 1;
		for(int i = head[x]; i; i = E[i].last){
			int v = E[i].v, l = E[i].l, r = E[i].r;
			if(d[x] > r) continue;
			if(h[v] <= r){
				if(max(d[x], max(h[v], l)) < d[v]){
					d[v] = max(d[x], max(h[v], l));
					q2.push((state2){v, d[v]});
				}
			}
		}
	}
}
int main(){
	freopen("lunch.in", "r", stdin);
	freopen("lunch.out", "w", stdout);
	n = read(), m = read();
	for(int i = 1; i <= m; i++){
		u = read(), v = read(), l = read(), r = read();
		add(u, v, l, r);
		add(v, u, l, r);
	}
	for(int i = 1; i <= n; i++){
		flag[i] = read();
	}
	for(int i = 1; i <= n; i++){
		if(flag[i] == -1) h[i] = INF, q1.push(state1{i, h[i]});
	}
	dijkstra1();
	for(int i = 1; i <= n; i++){
		if(h[1] > 0){
			printf("Impossible\n");
			return 0;
		}
	}
	memset(d, 0x3f, sizeof d);
	d[1] = 0;
	q2.push((state2){1, 0});
	dijkstra2();
	for(int i = 1; i <= n; i++){
		if(flag[i] == 1 && d[i] == 0x3f3f3f3f){
			printf("Impossible\n");
			return 0;
		}
	}
	printf("JJXSM\n");
	return 0;
}

C.老杰克哒

在这里插入图片描述

分析:
      首先我们把区间内划分成若干 1 1 1 的连续段,那么对于一段,最多花费 2 2 2 的代价把它消除:我们可以现在后面加1,然后进位后在前面减1。并且一段至少需要花费1的代价。
      基于上面的想法,我们可以考虑从后往前扫段,如果当前段长度大于1,那么就让它进位,否则就直接删掉。注意:进位后可能会与前面组成1段。所以这样做时肯定优的。贪心可以得到 50pts。
      但是这样做没有什么优化的空间。我们考虑dp。
      设 d p i , 0 / 1 dp_{i, 0/1} dpi,0/1 表示从开头到 i i i,字符串变成先一段连续的 0 0 0,然后一段连续的 0 / 1 0/1 0/1 的最小代价。考虑转移:

      如果第 i i i 位是 0 0 0

      d p i , 0 ← d p i − 1 , 0 dp_{i, 0} \leftarrow dp_{i-1, 0} dpi,0dpi1,0 d p i , 0 ← d p i − 1 , 1 + 2 dp_{i,0} \leftarrow dp_{i-1, 1} + 2 dpi0dpi1,1+2
      d p i , 1 ← d p i − 1 , 0 + 1 dp_{i, 1} \leftarrow dp_{i - 1, 0} + 1 dpi,1dpi1,0+1 d p i , 1 ← d p i − 1 , 1 + 1 dp_{i, 1} \leftarrow dp_{i - 1, 1} + 1 dpi,1dpi1,1+1

      解释一下上面的转移, d p i , 0 dp_{i, 0} dpi,0 可以由 d p i − 1 , 0 dp_{i - 1, 0} dpi1,0 转移而来,代表什么也不操作, d p i , 0 dp_{i, 0} dpi,0 d p i − 1 , 1 + 2 dp_{i - 1, 1} + 2 dpi1,1+2 转移过来,代表我们可以通过加1减1两次操作把前面的一段1给消除完,这样多的花费是2。 d p i , 1 dp_{i, 1} dpi,1 的转移同理。

      如果第 i i i 位是 1 1 1

      d p i , 0 ← d p i − 1 , 0 + 1 dp_{i, 0} \leftarrow dp_{i - 1, 0} + 1 dpi,0dpi1,0+1 d p i , 0 ← d p i − 1 , 1 + 2 dp_{i, 0} \leftarrow dp_{i - 1, 1} + 2 dpi,0dpi1,1+2
      d p i , 1 ← d p i − 1 , 0 dp_{i, 1} \leftarrow dp_{i - 1, 0} dpi,1dpi1,0 d p i , 1 ← d p i − 1 , 1 dp_{i, 1} \leftarrow dp_{i - 1, 1} dpi,1dpi1,1
      这转移和上面的是同理的。

      那么对每一次询问,我们设左端点是 s t st st,实际上就是按照 S s t S_{st} Sst 的类型给 d p s t , 0 / 1 dp_{st, 0/1} dpst,0/1 一个初值,然后 O ( n ) O(n) O(n)转移。

      我们发现转移是取 m i n min min,并且这个转移方式只跟当前为字符是 0 0 0 还是 1 1 1 有关。并且和矩阵乘法很想。我们对应 0 0 0 1 1 1,直接构造两种矩阵,然后用线段树维护区间内矩阵的乘积,加速转移就好了。

CODE:

#include<bits/stdc++.h>// 每一次转移可以看做是乘一个矩阵 
using namespace std;// 用线段树维护矩阵的乘积
const int N = 3e5 + 10;
struct matrix{
	int mt[2][2];
	friend matrix operator * (matrix a, matrix b){
		matrix c; memset(c.mt, 0x3f, sizeof c.mt);
		for(int i = 0; i <= 1; i++)
			for(int j = 0; j <= 1; j++)
				for(int k = 0; k <= 1; k++)
					c.mt[i][j] = min(c.mt[i][j], a.mt[i][k] + b.mt[k][j]);
		return c;
	}
};
matrix m1, m2;
struct SeqmentTree{
	int l, r; matrix mt;
	#define l(x) t[x].l
	#define r(x) t[x].r
	#define mt(x) t[x].mt
}t[N * 4]; 
int n, m, opt, x, y;
char str[N];
int read(){
	int x = 0, f = 1; char c = getchar();
	while(!isdigit(c)){if(c == '-') f = -1; c = getchar();}
	while(isdigit(c)){x = (x << 1) + (x << 3) + (c ^ 48); c = getchar();}
	return x * f;
}
void build(int p, int l, int r){
	l(p) = l, r(p) = r;
	if(l == r) return ;
	int mid = (l + r >> 1);
	build(p << 1, l, mid);
	build(p << 1 | 1, mid + 1, r);
}
void update(int p){mt(p) = mt(p << 1) * mt(p << 1 | 1);}
void ins(int p, int pos, matrix c){
	if(l(p) == r(p)){
		mt(p) = c;
		return ;
	}
	int mid = (l(p) + r(p) >> 1);
	if(pos <= mid) ins(p << 1, pos, c);
	else ins(p << 1 | 1, pos, c);
	update(p);
}
matrix ask(int p, int l, int r){
	if(l <= l(p) && r >= r(p)) return mt(p);
	int mid = (l(p) + r(p) >> 1);
	if(r <= mid) return ask(p << 1, l, r);
	else if(l > mid) return ask(p << 1 | 1, l, r);
	else return ask(p << 1, l, r) * ask(p << 1 | 1, l, r);
}
int query(int l, int r){
	matrix res;
	if(str[l] == '1') res.mt[0][0] = 1, res.mt[0][1] = 0;
	else res.mt[0][0] = 0, res.mt[0][1] = 1;
	if(l == r) return res.mt[0][0];
	matrix tmp = ask(1, l + 1, r);
	res = res * tmp;
	return res.mt[0][0];
}
int main(){
	freopen("string.in", "r", stdin);
	freopen("string.out", "w", stdout);
	n = read(); 
	scanf("%s", str + 1);
	int len = strlen(str + 1);
	m1.mt[0][0] = 0; m1.mt[0][1] = 1; m1.mt[1][0] = 2; m1.mt[1][1] = 1;
	m2.mt[0][0] = 1; m2.mt[0][1] = 0; m2.mt[1][0] = 2; m2.mt[1][1] = 0;
	build(1, 1, n);
	for(int i = 1; i <= len; i++){
		if(str[i] == '0') ins(1, i, m1);
		else ins(1, i, m2);
	}
	m = read();
	for(int i = 1; i <= m; i++){
		opt = read(), x = read(), y = read();
		if(opt == 1) printf("%d\n", query(x, y));
		else{
			if(y == 0) ins(1, x, m1);
			else ins(1, x, m2);
			str[x] = (y + '0');
		}
	}
	return 0;
}

D.季积晓淆

在这里插入图片描述

分析:
会不了一点

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/112124.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

vsCode安装CodeRunner插件输出中文乱码问题

1 vsCode下载 vcCode官网地址&#xff1a;https://code.visualstudio.com/ 2 安装CodeRunner 通过Ctrl Shift P 找到 settings找到code-runner.executorMap&#xff0c;在 settings.json 中加入 "code-runner.executorMap": {....."python": "s…

上班族如何做日程自律清单实现逆袭呢?电脑日程管理软件助力高效办公

越来越多的上班族都表示自己每天的工作任务非常多&#xff0c;经常从早忙到晚也无法按时完成工作&#xff0c;导致工作的拖延完成&#xff0c;这应该怎么办呢&#xff1f;其实对于职场人士来说&#xff0c;想要在工作中提升效率&#xff0c;就需要提前做好每天的工作日程安排&a…

如何在Android设备上检查应用程序使用情况,包括使用时间

你可能不知道自己花了多少时间在手机上。很可能你一天中有一半的时间都在盯着手机屏幕。如果你怀疑这一事实,你会很快核实的。在这篇文章中,我们将向你介绍如何在Android设备上检查应用程序的使用情况。 如何在Android上检查应用程序电池使用情况 你使用时间最长的应用程序…

腾讯云轻量级服务器哪个镜像比较好?

腾讯云轻量应用服务器镜像是什么&#xff1f;镜像就是操作系统&#xff0c;轻量服务器镜像系统怎么选择&#xff1f;如果是用来搭建网站腾讯云百科txybk.com建议选择选择宝塔Linux面板腾讯云专享版&#xff0c;镜像系统根据实际使用来选择&#xff0c;腾讯云百科来详细说下腾讯…

2023年四川省网络与信息安全技能大赛 决赛个人赛Writeup

文章目录 Web前端验证PHP_Try MiscHelloWorld密码在这easy_log Cryptobaser 线下“断网”CTF个人赛&#xff0c;题都很简单(新手级难度)&#xff0c;总共10道题目&#xff0c;解了6题。 赛题附件请自取&#xff1a; 链接&#xff1a;https://pan.baidu.com/s/1lgNEBO7a1L4KLE2t…

Academic Inquiry|如何阅读英文文献

相关素材&#xff1a; 知云文献阅读器、谷粉学术 相关可借鉴文章&#xff1a; [1]Academic Inquiry|国外文献查找-CSDN博客 [2]Academic accumulation|英文文献速读-CSDN博客 [3]Academic Inquiry|edge、chrome浏览器插件配置及相关问题解答-CSDN博客 一、相关素材准备 &#…

最新Ai智能创作系统源码V3.0,AI绘画系统/支持GPT联网提问/支持Prompt应用+搭建部署教程

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

kubernetes-service微服务

目录 一、service微服务 二、Ipvs模式 三、ClusterIP 1.ClusterIP 2.headless 四、NodePort 1.NodePort 2.默认端口 五、LoadBalancer 1.LoadBalancer 2.metallb 六、ExternalName 一、service微服务 Kubernetes Service微服务是一种基于Kubernetes的微服务架构&…

智慧矿山:AI算法在带式运输机中的异物识别应用

随着现代农业和工业的发展&#xff0c;带式运输机在各种生产作业中发挥着越来越重要的作用。然而&#xff0c;在带式运输机运行过程中&#xff0c;可能会混入各种异物&#xff0c;这些异物的存在可能会对运输过程和设备本身造成损害。为了解决这一问题&#xff0c;本文将介绍一…

一个极好用的浏览器标签页插件

这是我登录后&#xff0c;并且上传了个人壁纸的页面 Br标签页 一 . 我们来看看界面和功能1.注册登录2.首页及右键功能3.添加小组件和app网址4.切换壁纸5. 计划页面 二 . Edge浏览器安装和chrome&#xff08;谷歌&#xff09;浏览器安装1. Edge浏览器安装2. chrome&#xff08;谷…

【java】命令行,包

文件夹情况&#xff1a; HelloWorld.java package com.demo; public class HelloWorld{public static void print(){System.out.println("HelloWorld!");}public static void main(String[] args){print();} } import.java import com.demo.HelloWorld; public cla…

K8S的pod创建过程

创建流程图 用户发起请求创建deployment&#xff1b;apiserver收到创建资源的请求&#xff0c;apiserver对客户端操作进行身份认证&#xff0c;认证完成后接受该请求&#xff0c;并把相关的信息保存到etcd中&#xff0c;然后返回确认信息给客户端&#xff1b;apiserver向etcd…

EDA常用数字器件硬件描述

EDA常用数字器件硬件描述 前言 在使用了一段时间EDA编程之后&#xff0c;来回顾一下基本的知识&#xff0c;看看如何实现基本的EDA常用数字器件对应的硬件描述 一、组合逻辑器件描述 1. 基本的逻辑门电路 与、或、非&#xff08;取反&#xff09;、与非、或非、异或、同或 …

Centos7安装Docker,安装DockerCompose(集群化部署),Docker私服镜像仓库

0.安装Docker Docker 分为 CE 和 EE 两大版本。CE 即社区版&#xff08;免费&#xff0c;支持周期 7 个月&#xff09;&#xff0c;EE 即企业版&#xff0c;强调安全&#xff0c;付费使用&#xff0c;支持周期 24 个月。 Docker CE 分为 stable test 和 nightly 三个更新频道…

数据结构第一课-----------数据结构的介绍

作者前言 &#x1f382; ✨✨✨✨✨✨&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f367;&#x1f382; ​&#x1f382; 作者介绍&#xff1a; &#x1f382;&#x1f382; &#x1f382; &#x1f389;&#x1f389;&#x1f389…

VueRouter 源码解析

重要函数思维导图 路由注册 在开始之前&#xff0c;推荐大家 clone 一份源码对照着看。因为篇幅较长&#xff0c;函数间的跳转也很多。 使用路由之前&#xff0c;需要调用 Vue.use(VueRouter)&#xff0c;这是因为让插件可以使用 Vue export function initUse(Vue: GlobalAP…

有哪些项目适合程序员业余时间做,并且短期内能赚点小钱?

要我说&#xff0c;程序员赚点小钱就别指望着自己搞个大项目了。 这几年的市场环境不好&#xff0c;如果你没点家底的话&#xff0c;打工攒的那点积蓄让你创业&#xff0c;一不小心就会血本无归。 对于程序员来说&#xff0c;最合适的还是给别人打工&#xff01;低风险稳定回款…

Vlice DM蓝牙5.2双模热插拔PCB

键盘使用说明索引&#xff08;均为出厂默认值&#xff09; 软件支持&#xff08;驱动的详细使用帮助&#xff09;一些常见问题解答&#xff08;FAQ&#xff09;首次使用步骤蓝牙配对规则&#xff08;重要&#xff09;蓝牙和USB切换键盘默认层默认触发层0的FN键配置的功能默认功…

创造产业链协同优势后,凌雄科技在DaaS行业转动成长飞轮

企业服务领域&#xff0c;一直存在一种共识&#xff1a;做好很难&#xff0c;但一旦服务模式跑通了&#xff0c;得到了市场的认可&#xff0c;要滚起雪球就会事半功倍。 重资产、重运营的DaaS&#xff08;设备及服务&#xff09;赛道&#xff0c;是个非常典型的细分领域。在这…

苹果AirTag固件更新

苹果公司针对其热销的物品追踪器 AirTag 于今天发布了新的固件更新&#xff0c;最新版本号为 2A61&#xff0c;但是这次更新苹果并未提供发布说明&#xff0c;所以目前还不知道这次更新有什么新内容。 关于这次更新&#xff0c;用户无法自己手动更新 AirTag 固件&#xff0c;因…