首页 > 其他分享 >CSP模拟30

CSP模拟30

时间:2023-10-01 11:11:22浏览次数:40  
标签:lc int 30 pl rc 区间 CSP 模拟 sub

CSP模拟30

难得改完一次题,写篇题解祭一下

A.枫(P7485 「Stoi2031」枫

考场居然打了个高分暴力

我的思路:假设我们已知最后一个数,逆推,不断往该数前(或后)加了多少数,直至完成这个操作。

荣获 $96pts$ 的好成绩 评测记录

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int M=1e6+10;
int T,q,n,m,wei;
int top,tail;
void dfs(int sum,int sub,int k,int c){
	if(sum==1){
		return;
	}
	dfs(sum-sub,(sum-sub-1)/(k+1)+1,k,c+1);
	if(c&1){
		int pl=1+(top-1)/k;
		top+=pl;
		tail+=sub-pl;
	}
	else {
		int pl=1+(tail-1)/k;
		top+=sub-pl;
		tail+=pl;
	}
}
int main(){
	scanf("%d",&T);
	for(int k=1;k<=T;k++){
		scanf("%d%d",&q,&m);
		for(int i=1;i<=q;i++){
			scanf("%d",&n);
			if(n==1||n==2){
				cout<<n<<' ';
				continue;
			}
			if(k>=n-1){
				cout<<n/2+1<<' ';
			}
			else if(k==n-2||k==n-3){
				cout<<(n+1)/2<<' ';
			}
			else {
				top=1,tail=1;
				dfs(n,(n-1)/(k+1)+1,k,1);
				cout<<top<<' ';
			}
		}
		cout<<'\n';
	}
	return 0;
}

正解

一些步骤相似,可不可以认为我敲了正解(bushi)

(fengwu大佬说) 给出了每次捡枫叶的最大枫叶数,显然是递推

我们求出当前个数第一次“挽回”的个数,求出下一状态的“思念”,插入一定的枫叶即可。(注意顺序

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int M=1e6+10;
int T,q,n,m;
int ans[M];
int main(){
	scanf("%d",&T);
	ans[1]=1;
	for(int k=1;k<=T;k++){
		scanf("%d%d",&q,&m);
		for(int i=2;i<=m;i++){
			int sum=i-(i-1)/(k+1)-1;
			int pos=sum-ans[sum]+1;
			ans[i]=pos+1+(pos-1)/k;
		}
		for(int i=1;i<=q;i++){
			scanf("%d",&n);
			cout<<ans[n]<<' ';
		}
		cout<<'\n';
	}
	return 0;
}

B.Little Elephant and Broken Sorting(Little Elephant and Broken Sorting)

概率期望都不做

规定$ f_{i,j}$表示第 $i$ 位上的数比第 $j$ 位上的数大的概率,n的范围很小,可以直接预处理。

每次交换,需要分类讨论:

1.两个位置都为交换的位置
2.其中一个位置为交换的位置

对于第一种情况,则 $f_{x,y}$ 与 $f_{y,x}$ 的值都为 $0.5$,原因显然。

对于第二种情况,既然有 $0.5$ 的概率更换,就需要将交换成功的概率加上交换失败的概率即可。

代码如下:

#include<bits/stdc++.h>
using namespace std;
const int M=5010;
int n,m;
int a[M];
double ans;
double f[M][M];
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++){
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			f[i][j]=(a[i]>a[j]);
		}
	}
	for(int i=1;i<=m;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		f[x][y]=f[y][x]=0.5;
		for(int j=1;j<=n;j++){
			if(j!=x&&j!=y){
				f[j][x]=f[j][y]=0.5*(f[j][x]+f[j][y]);
				f[x][j]=f[y][j]=0.5*(f[x][j]+f[y][j]);
			}
		}
	}
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(i!=j){
				ans+=f[i][j];
			}
		}
	}
	printf("%0.9lf",ans);
	return 0;
}

C.楼房重建(P4198 楼房重建)

神奇+抽象线段树

我们需要不断的区间查询和区间修改,联想到线段树

已知当一个建筑的斜率大于前面所有建筑的斜率时,该建筑可以被看到,所以我们进行 $update$ 。


合并操作是难点。

设当前区间为 $c$ ,左区间为 $lc$ ,右区间为 $rc$ 。

首先 $lc$ 的答案是可以直接加入 $c$ 的答案的,原因显然。

但是 $rc$ 的答案比较特殊,可能会被 $lc$ 遮挡,需要分类讨论。

1. 如果c的最大值在lc,那么rc的所有建筑一定都会被阻挡,直接返回lc的答案。
2.如果c的最大值在rc,我们还需要再分:
	- 如果rc的左区间的最大值比lc的最大值大,我们直接加上rc的右区间的答案,并递归rc的左区间。
    - 否则直接递归rc的右区间即可。

代码如下:

#include<bits/stdc++.h>
#define lc c<<1
#define rc c<<1|1
using namespace std;
const int M=1e5+10;
struct abc{
	int l,r,num;
	double k;
}t[M<<2];
int n,m;
void add(int l,int r,int c){
	t[c].l=l; t[c].r=r;
	if(l==r){
		return;
	}
	int mid=(l+r)>>1;
	add(l,mid,lc);
	add(mid+1,r,rc);
}
int query(double ma,int c){
	if(t[c].k<=ma){
		return 0;
	}
	if(t[c].l==t[c].r){
		return 1;
	}
	if(t[lc].k>ma){
		return query(ma,lc)+t[c].num-t[lc].num;
	}
	else {
		return query(ma,rc);
	}
}
void update(int x,double va,int c){
	if(t[c].l==x&&t[c].r==x){
		t[c].num=1;
		t[c].k=va;
		return;
	}
	int mid=(t[c].l+t[c].r)>>1;
	if(x<=mid){
		update(x,va,lc);
	}
	else {
		update(x,va,rc);
	}
	t[c].k=max(t[lc].k,t[rc].k);
	t[c].num=t[lc].num+query(t[lc].k,rc);
}
int main(){
	scanf("%d%d",&n,&m);
	add(1,n,1);
	for(int op=1;op<=m;op++){
		int x,y;
		scanf("%d%d",&x,&y);
		update(x,(double)y/x,1);
		cout<<t[1].num<<'\n'; 
	}
	return 0;
}

D.Yes or No([AGC019F] Yes or No)

人生第二黑

但是讲不清楚,建议出门右转,找大佬小粉兔

肯定不是不想打了

标签:lc,int,30,pl,rc,区间,CSP,模拟,sub
From: https://www.cnblogs.com/Airposs/p/17738662.html

相关文章

  • 9.30随笔
    →信条部分早起晚睡2/88,+0举止厚重12/360,,+1穴位按摩2/30,+1每日反省1/90,+0总结→持续摆烂中→学习部分[√]单词[√]跑步→项目进度无......
  • 9.30 读书笔记
    《代码大全2》是一个经典的软件开发书籍,是一本非常有价值的资源,包含了许多软件开发中的重要主题。书中提醒读者以解决问题为导向,不仅仅是完成任务。防御式编程,防御式编程不是指不让别人批评代码,而是指确保要承担的责任,保证方法不会因为传入错误数据而破坏,看似微小的防范,收益可能......
  • 2023.9.30
    得了支气管炎,上午去医院挂水,下午回来,继续解决之前pwn相关东西遇到的一些问题,今天是去把新的ubuntu虚拟机也装了个vmware_tool,然后LibcSearcher有点问题没法用,花了很长时间搞定这个最后实验可行。明天继续......
  • 9.28-9.30有感
    持续摆烂的3天,不是不想写日记,而是什么事情都没做,不知道写啥,干嘛去了呢,主要是看小说和打游戏,白天就想睡觉,晚上打游戏的恶性循环,晚上没睡好,白天就不想动。手机误人啊。但又很难真的不去看,这就很矛盾......
  • 2023-2024-1 20231304《计算机基础与程序设计》第一周学习总结
    2023-2024-120231304《计算机基础与程序设计》第一周学习总结作业信息这个作业属于哪个课程<班级的链接>2023-2024-1-计算机基础与程序设计这个作业要求在哪里<作业要求的链接>2023-2024-1计算机基础与程序设计第一周作业这个作业的目标快速浏览预习《计算机科......
  • 202309301820_《Spring boot项目,继承mybatis-generator遇到的问题及解决》
     当配置到最后,双击右侧maventab,准备生成时,报红:1.“Loadingclass`com.mysql.jdbc.Driver'.Thisisdeprecated.Thenewdriverclassis`com.mysql.cj.jdbc.Driver'.ThedriverisautomaticallyregisteredviatheSPIandmanualloadingofthedriverclassisgen......
  • 2023.9.30日报
    今天学习了部分vue的开发知识,了解了一部分vue的运作原理,即先定义数据,然后生成对应的app,然后嵌入到对应的div视图中即可,在这个过程中,起初使用的是vscode,但是没有查找到对应的启动html的插件,因此还是转到了idea......
  • 2023-09-30:用go语言,给你一个整数数组 nums 和一个整数 k 。 nums 仅包含 0 和 1, 每一
    2023-09-30:用go语言,给你一个整数数组nums和一个整数k。nums仅包含0和1,每一次移动,你可以选择相邻两个数字并将它们交换。请你返回使nums中包含k个连续1的最少交换次数。输入:nums=[1,0,0,1,0,1],k=2。输出:1。来自左程云。答案2023-09-30:步骤描述:1.......
  • 温度由分类变量和连续变量决定,请用python机器学习三种方法模拟生成数据并拟合
    要模拟生成数据并拟合温度(或任何其他目标变量),通常需要考虑以下步骤:生成特征数据:创建分类变量和连续变量,这些变量将用于预测温度。分类变量可以是例如季节、天气状况(晴天、雨天、多云等),而连续变量可以是例如湿度、风速等。生成目标数据:根据特征数据和某种关系生成目标变量(温度)的数据......
  • 2023-2024-1 20231303赵泊瑄《计算机基础与程序设计》第一周学习总结
    2023-2024-1学号20231303,《计算机基础与程序设计》第一周学习总结作业信息这个作业属于哪个课程https://edu.cnblogs.com/campus/besti/2023-2024-1-CFAP这个作业的要求在哪里https://www.cnblogs.com/rocedu/p/9577842.html#WEEK01这个作业的目标课程概论、工......