首页 > 其他分享 >2023.5.7拷逝

2023.5.7拷逝

时间:2023-06-04 22:12:21浏览次数:41  
标签:minn int long 2023.5 拷逝 include mod 逆序

T1

假设交换了 \(a[i]\) 和 \(a[i+1]\) ,那么 \(a[1...i-1]\) , \(a[i+2...n]\) 与这两个数构成的逆序对不变。只有 \(a[i]\) 和 \(a[i+1]\) 两个数构成的逆序对可能发生改变。

如果 \(a[i]<a[i+1]\) ,那么逆序对个数加\(+1\);如果 \(a[i]=a[i+1]\) ,那么逆序对个数不变;如果 \(a[i]>a[i+1]\) ,那么逆序对个数\(-1\)。

另外,此题需要特别注意:当 \(n=1e6\) 时,逆序对个数最多可能为 \(n\times (n-1)/2\) ,需要用\(long\) \(long\)。

\(code:\)

#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,c,ans,x,a[1000005];
int main(){
	freopen("seq.in","r",stdin);
	freopen("seq.out","w",stdout);
	scanf("%lld%lld%lld",&n,&m,&c);
	for(int i=1;i<=n;++i)
		scanf("%lld",&a[i]);
	for(int i=1;i<=m;++i){
		scanf("%lld",&x);
		if(a[x]<a[x+1])
			++c;
		else if(a[x]>a[x+1])
			--c;
		ans^=c;
		swap(a[x],a[x+1]);
	}
	printf("%lld\n",ans);
	fclose(stdin);fclose(stdout);
	return 0;
}

T2

不难发现,如果存在逆序对,那么最近的逆序对距离一定是1。所以只需要检查这个数列是否存在逆序对,即是否不单调递增即可。

\(code:\)

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int t,n,a[5];
int read(){
	char g;int w=0,f=1;bool ok=0;
	while(1){
		g=getchar();
		if(g=='-')
			ok=1,f=-1;
		else if(g>='0'&&g<='9')
			ok=1,w=w*10+f*(int)(g-'0');
		else if(ok) break;
	}
	return w;
}
int main(){
	freopen("distance.in","r",stdin);
	freopen("distance.out","w",stdout);
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		int ok=0;
		for(int i=1;i<=n;++i){
			a[i&1]=read();
			if(i!=1&&a[i&1]<a[(i-1)&1])
				ok=1;
		}
		printf("%d\n",ok);
	}
	fclose(stdin);fclose(stdout);
	return 0;
}

T3

对于一个数 \(a[i]\) ,设 \(a[j](j>i)\) 是整个数列中最靠后的小于 \(a[i]\) 的数。此时 \(a[i]\) 与 \(a[j]\) 能够连边。对于任意的 \(k(i<k<j)\) :① \(a[k]<a[j]<a[i]\) ,此时 \(i\) 和 \(k\) 能连边;② \(a[j]<a[k]\) ,此时 \(j\) 和 \(k\) 能连边。综上,我们发现: \([i,j]\) 中的所有数一定处在一个联通块中。

首先预处理一个数组 \(minn[i]\) ,表示 \([i,n]\) 中所有数的最小值。

接下来扫描这个序列。设当前的数下标为 \(i\) , \(t\) 为当前数所在联通块的右端点。

当 \(i>t\) 时,说明当前的数已经离开了上一个联通块,出现了一个新联通块。

之后从 \(t\) 开始扫描后面的数,设扫描的数为 \(j\) ,直到 \(minn[j]<=a[i]\&\&minn[j+1]>a[i]\) 时停止循环,并用 \(j\) 更新 \(t\) 。因为此时 \(a[j]\) 是整个数列中最靠后的小于 \(a[i]\) 的数,\([i,j]\) 中的所有数一定处在一个联通块中,导致 \(i\) 所处的联通块得以扩充。

\(code:\)

#include<iostream>
#include<ctime>
#include<cstdio>
using namespace std;
int n,a[5000005],ans,t,minn[5000005],st=clock();
int read() {
    int s=0,f=1;char ch=getchar();
    while(ch<'0' || ch>'9')	{if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0' && ch<='9'){s=(s<<3)+(s<<1)+(ch^48);ch=getchar();}
    return s*f;
}
int main(){
	//freopen("block.in","r",stdin);
	//freopen("block.out","w",stdout);
	scanf("%d",&n);
	for(int i=1;i<=n;++i)
		a[i]=read();
	minn[n]=a[n];
	if(minn[n]<=a[1])
		printf("1\n");
	else{
		for(int i=n-1;i>=1;--i){
			minn[i]=min(minn[i+1],a[i]);
			if(!t&&minn[i]<=a[1]&&minn[i+1]>a[1])
				t=i;
		}
		ans=1;
		for(int i=2;i<=n;++i){
			if(i>t){
				++ans;t=i;
			}
			for(int j=t;j<=n;++j){
				if(j==t&&minn[j]>a[i])
					break;
				if((minn[j]<=a[i]&&minn[j+1]>a[i])||(j==n&&minn[j]<=a[i])){
					t=j;break;
				}
			}
		}
		printf("%d\n",ans);
	}
	fclose(stdin);fclose(stdout);
	return 0;
}

T4(50pts)

首先不难想到朴素的DP:设 \(f[i][j]\) 表示前 \(i\) 个数,逆序对个数为 \(j\) 的方案数。对于第 \(i\) 个数,它与前面的数可以构成 \(0\) 或 \(1\) 或 \(2\) ...或 \(i-1\) 个逆序对。因此 \(f[i][j]\) 可以由 \(f[i-1][k](max(j-i+1,0)<=k<=j)\) 转移而来。状态转移方程:\(f[i][j]= \sum f[i-1][k](max(j-i+1,0)<=k<=j)\)。时间复杂度\(O(n^3)\)。

接下来考虑优化。设当\(for\) 循环到 \(j\) 时, \(s= \sum f[i-1][k](max(j-i+1,0)<=k<=j)\)。那么当\(for\) 循环到 \(j-1\) 时, \(s= \sum f[i-1][k](max(j-i,0)<=k<=j-1)\) ,只需令此时的 \(s\) 加上 \(f[i-1][j]-f[i-1][j-i]\) ,即可得到 \(j\) 时的 \(s\) ,然后直接用 \(s\) 更新 \(f[i][j]\) 。时间复杂度\(O(n^2)\)。

\(code:\)

#include<iostream>
#include<cstdio>
using namespace std;
long long n,m,f[2][1000005],s;
const long long mod=1e9+7;
int main(){
	freopen("count.in","r",stdin);
	freopen("count.out","w",stdout);
	scanf("%lld%lld",&n,&m);
	f[0][0]=1;
	for(int i=1;i<=n;++i){
		s=0;
		for(int j=0;j<=m;++j){
			if(j-i>=0)
				s=(s-f[(i-1)&1][j-i]+mod)%mod;
			s=(s+f[(i-1)&1][j])%mod;
			f[i&1][j]=s%mod;
		}
  	}
	printf("%lld\n",f[n&1][m]%mod);
	fclose(stdin);fclose(stdout);
	return 0;
}

标签:minn,int,long,2023.5,拷逝,include,mod,逆序
From: https://www.cnblogs.com/andyl/p/17456486.html

相关文章

  • 2023.6.4拷逝
    #T1首先题目没有强制让我们一起算$k^{r(p)}+r^2(p)$,我们可以把它拆成两部分,一部分是$k^{r(p)}$,一部分是$r^2(p)$。考虑递推求解两个部分。先看第一个部分。设$n$的全排列的逆序对个数分别是$p_1,p_2,...,p_{n!}$,并假设我们已经知道$k^{r(p)}$的值。现在新增一个数$n......
  • 2023.5 codeforces 杂题选做
    2023.5codeforces杂题选做E.Location\(n\le5\times10^4\)的范围,并且区间赋值、区间维护最值,可以考虑分块。然后对于散块的修改可以直接暴力,对于整块,由于\(b_i\)值不变,\(a_i\)值只有一个,思考如何快速求。由于\(\dfrac{\operatorname{lcm}(a_i,b_i)}{\gcd(a_i,b_i)}=\d......
  • SequoiaDB分布式数据库2023.5月刊
    本月看点速览行业认可,荣登中国最佳信创厂商系列榜单聚焦创新,入选2022年大湾区科创企业创新TOP10科技为本,协同发展,多家组织机构到访青杉计划2023已开启,一起攀登更高的“杉” 行业认可,荣登中国最佳信创厂商系列榜单近日,由第一新声联合天眼查发起的2023年中国最佳信创厂......
  • 2023.5.31——软件工程站立会议(阶段二)
    站立会议内容:1.整个项目预期的任务量:目前已经花的时间:剩余的时间:2.任务看板照片: 3.团队照片: 4.产品状态:最新做好的功能:正在完成中5.燃尽图:......
  • 2023.5.31——软件工程日报
    所花时间(包括上课):6h代码量(行):0行博客量(篇):1篇今天,上午学习,下午考数据库。我了解到的知识点:1.了解了一些数据库的知识;2.了解了一些python的知识;3.了解了一些英语知识;5.了解了一些Javaweb的知识;4.了解了一些数学建模的知识;6.了解了一些计算机网络的知识;......
  • 2023.5.31 Linux系统⽤户管理
    1.⽤户基本概述1.1⽤户相关的命令1.2⽤户创建的原理2.⽤户密码管理3.组的基本管理4.⽤户身份切换5.⽤户身份提权6.⽇志相关审计1.⽤户基本概述Linu属于多⽤户操作系统,在windows中,可以创建多个⽤户,但不允许同⼀时间多个⽤户进⾏系统登陆,但是Linux可以同时⽀持多个⽤户同时登陆......
  • 2023.5.31-Linux系统基本权限
    02.Linux系统基本权限1.权限修改命令chmod2.属主属组修改命令chown3.基础权限设置案例Linux中的⽂件或⽬录的权限和⽤户及⽤户组关联很⼤,Linux中每个⽂件或⽬录都有⼀组共9个基础权限位,每三个字符被分为⼀组,他们分别是属主权限位(占三个字符)、属组权限位(占三个字符)、其他⽤户权......
  • 2023.5.31每日总结
    <%--CreatedbyIntelliJIDEA.User:王磊Date:2023/5/29Time:15:52TochangethistemplateuseFile|Settings|FileTemplates.--%><%@pageimport="softwareengin.teacher"%><%@pageimport="softwareengin.AllMet......
  • 2023.5.30每日总结
    publicexamination[]sortAll2()throwsException{Stringsql="selectcount(*)fromexaminationwheregrade<60";PreparedStatementpre=connect.prepareStatement(sql,ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_READ......
  • 2023.5.30《人件》阅读笔记
    第三章——软件工程师的成长考级之路:在中国,软件工程师的职业资格考试有:计算机等级考试和全国计算机技术与软件专业技术资格考试。很多公司也提供了针对自己产品的职业认证项目。例如:微软公司有微软认证专家甲骨文公司有Oracle认证项目。本章主要讲了,不同级别的......