蓝桥杯模板题

A::::::::::::::::小明的彩灯:(差分)

【问题描述】

小明拥有 N 个彩灯,第 i 个彩灯的初始亮度为 ai​。

小明将进行 Q 次操作,每次操作可选择一段区间,并使区间内彩灯的亮度 +x(x 可能为负数)。

求 Q 次操作后每个彩灯的亮度(若彩灯亮度为负数则输出 0)。

【输入格式】

第一行包含两个正整数 N,Q,分别表示彩灯的数量和操作的次数。

第二行包含 N 个整数,表示彩灯的初始亮度。

接下来 Q 行每行包含一个操作,格式如下:

  • l r x,表示将区间 l∼r 的彩灯的亮度 +x。

【输出格式】

输出共 1 行,包含 N 个整数,表示每个彩灯的亮度。

【样例输入】

5 3
2 2 2 1 5
1 3 3
4 5 5
1 1 -100

【样例输出】

0 5 5 6 10

【评测数据规模】

对于所有评测数据,1≤N,Q≤5×105,0≤ai​≤109,11≤l≤r≤N,−109≤x≤109。

#include <iostream>
using namespace std;
int n,m;
long long a[500005];
long long b[500005];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		b[i]=a[i]-a[i-1];
	}
	for(int i=1;i<=m;i++){
		int l,r;
		long long x;
		cin>>l>>r>>x;
		b[l]=b[l]+x;
		b[r+1]=b[r+1]-x;
		
	}
	for(int i=1;i<=n;i++){
		a[i]=b[i]+a[i-1];
	}
	for(int i=1;i<=n;i++){
		if(a[i]<0){
			cout<<0<<' '; 
		}else{
			cout<<a[i]<<' ';
		}
	}
	return 0;
}

 B::::::::::::::::解立方根:(二分)

题目描述

给定一个正整数 N,请你求 N 的立方根是多少。

输入描述

第 1 行为一个整数 T,表示测试数据数量。

接下来的 T 行每行包含一个正整数 N。

1≤T≤105,0≤N≤105。

输出描述

输出共 T 行,分别表示每个测试数据的答案(答案保留 3 位小数)。

输入输出样例

示例 1

输入

3
0
1
8

输出

0.000
1.000
2.000

运行限制

  • 最大运行时间:5s
  • 最大运行内存: 128M
#include <iostream>
#include <stdio.h>
#include <cmath>
using namespace std;
int t,n;
double l(int n){
	double l=0,r=1e5;
	double res=0;
	while(r>=l){
		double mid=(l+r)/2.0;
		if(mid*mid*mid-n>1e-12){
			r=mid-0.000001;
		}else if(mid*mid*mid-n<-1e-12){
			l=mid+0.000001;
			res=mid;
		}else{
			return mid;
		}

	}

}
int main(){
	cin>>t;
	for(int i=0;i<t;i++){
		cin>>n;
		printf("%.3lf\n",l(n));
	}
	return 0;
}

 C:::::::::::::::::走迷宫(BFS)

题目描述

给定一个 N×M 的网格迷宫 G。G 的每个格子要么是道路,要么是障碍物(道路用 1 表示,障碍物用 0 表示)。

已知迷宫的入口位置为(x1​,y1​),出口位置为 (x2​,y2​)。问从入口走到出口,最少要走多少个格子。

输入描述

输入第 1行包含两个正整数 N,M,分别表示迷宫的大小。

接下来输入一个 N×M 的矩阵。若 Gi,j​=1 表示其为道路,否则表示其为障碍物。

最后一行输入四个整数x1​,y1​,x2​,y2​,表示入口的位置和出口的位置。

1≤N,M≤102,0≤Gi,j​≤1,1≤x1​,x2​≤N,1≤y1​,y2​≤M。

输出描述

输出仅一行,包含一个整数表示答案。

若无法从入口到出口,则输出 -1−1。

输入输出样例

示例 1

输入

5 5 
1 0 1 1 0
1 1 0 1 1 
0 1 0 1 1
1 1 1 1 1
1 0 0 0 1
1 1 5 5 

输出

8

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
#include <iostream>
#include <queue>
using namespace std;
int n,m;
int ans;
int a[105][105];
int b[4][2]={
   
   {-1,0},{0,-1},{1,0},{0,1}};
bool flage;
int x1,y1,x2,y2;
struct zuo{
	int x,y;
	int r;
	zuo(int xx,int yy,int rr){
		x=xx;
		y=yy;
		r=rr;
	}
};
queue<zuo> q;
bool c[105][105];
bool check(int x,int y){
	return x>0&&x<=n&&y>0&&y<=m;
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			cin>>a[i][j];
		}
	}
	cin>>x1>>y1>>x2>>y2;
	q.push(zuo(x1,y1,0));
	c[x1][y1]=1;
	while(!q.empty()){
		int x=q.front().x;
		int y=q.front().y;
		int r=q.front().r;
		q.pop();
		if(x==x2&&y==y2){
			ans=r;
			flage=true;
			break;
		}
		for(int i=0;i<4;i++){
			int tx=x+b[i][0];
			int ty=y+b[i][1];
			if(check(tx,ty)&&a[tx][ty]==1&&!c[tx][ty]){
				c[tx][ty]=1;
				int rr=r+1;
				q.push(zuo(tx,ty,rr));
			}
		}
		
	}
	if(flage){
		cout<<ans;
	}else{
		cout<<-1;
	}

	return 0;
} 

  D:::::::::::::::::小明的背包(01背包问题)

题目描述

小明有一个容量为 V 的背包。

这天他去商场购物,商场一共有 NN 件物品,第 ii 件物品的体积为 wi​,价值为 vi​。

小明想知道在购买的物品总体积不超过 VV 的情况下所能获得的最大价值为多少,请你帮他算算。

输入描述

输入第 1 行包含两个正整数 N,V,表示商场物品的数量和小明的背包容量。

第 2∼N+1 行每行包含 2 个正整数 w,v,表示物品的体积和价值。

1≤N≤102,1≤V≤103,1≤wi​,vi​≤103。

输出描述

输出一行整数表示小明所能获得的最大价值。

输入输出样例

示例 1

输入

5 20
1 6
2 5
3 8
5 15
3 3 

输出

37

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 128M
#include <iostream>
#include <cmath>
using namespace std;
int n;
int wi[105];
int vi[105];
int dp[105][10005]; 
int v;
int main(){
	cin>>n>>v;
	for(int i=1;i<=n;i++){
		cin>>wi[i]>>vi[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=v;j++){
      dp[i][j]=dp[i-1][j];
			if(j>=wi[i]){
				dp[i][j]=max(dp[i-1][j],dp[i-1][j-wi[i]]+vi[i]);
			}
				
			
		}
	}
	cout<<dp[n][v];
	return 0;
} 

   E:::::::::::::::::小明的衣服(哈曼夫树)

题目描述

小明买了 n 件白色的衣服,他觉得所有衣服都是一种颜色太单调,希望对这些衣服进行染色,每次染色时,他会将某种颜色的所有衣服寄去染色厂,第 ii 件衣服的邮费为 ai​ 元,染色厂会按照小明的要求将其中一部分衣服染成同一种任意的颜色,之后将衣服寄给小明, 请问小明要将 nn 件衣服染成不同颜色的最小代价是多少?

输入描述

第一行为一个整数 n ,表示衣服的数量。

第二行包括 n 个整数 a1​,a2​...an​ 表示第 i 件衣服的邮费为 ai​ 元。

(1≤n≤105,1≤ai​≤109 )

输出描述

输出一个整数表示小明所要花费的最小代价。

输入输出样例

示例 1

输入

5
5 1 3 2 1 

输出

25

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M

#include <iostream>
#include <queue>
using namespace std;
long long ans;
priority_queue<long long,vector<long long>,greater<long long> > q;
int n;
int main(){
	cin>>n;
	for(int i=0;i<n;i++){
		long long ai;
		cin>>ai;
		q.push(ai);
	}
	while(q.size()!=1){
		long long a=q.top();
		q.pop();
		long long b=q.top();
		q.pop();
		ans+=a+b;
		q.push(a+b);
	}
	cout<<ans;
	return 0;
}

   F:::::::::::::::::蓝桥骑士(LIS求最长递增序列)

题目描述

小明是蓝桥王国的骑士,他喜欢不断突破自我。

这天蓝桥国王给他安排了 NN 个对手,他们的战力值分别为 a1​,a2​,...,an​,且按顺序阻挡在小明的前方。对于这些对手小明可以选择挑战,也可以选择避战。

身为高傲的骑士,小明从不走回头路,且只愿意挑战战力值越来越高的对手。

请你算算小明最多会挑战多少名对手。

输入描述

输入第一行包含一个整数 N,表示对手的个数。

第二行包含 N 个整数 a1​,a2​,...,an​,分别表示对手的战力值。

1≤N≤3×105,1≤ai​≤109。

输出描述

输出一行整数表示答案。

输入输出样例

示例 1

输入

6
1 4 2 2 5 6

输出

4

#include <iostream>
#include <algorithm>
using namespace std;
int n;
long long a[300005];
long long dp[300005];
long long LIS(int n){
	dp[1]=a[1];
	int ans=2;
	for(int i=2;i<=n;i++){
		if(dp[ans-1]<a[i]){
			dp[ans]=a[i];
			ans++;
		}else{
			dp[lower_bound(dp+1,dp+ans,a[i])-dp]=a[i];
		}
	}
	return ans-1;
}
int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	cout<<LIS(n);
	return 0;
}

   G:::::::::::::::::蓝桥幼儿园(并查集)

题目描述

蓝桥幼儿园的学生是如此的天真无邪,以至于对他们来说,朋友的朋友就是自己的朋友。

小明是蓝桥幼儿园的老师,这天他决定为学生们举办一个交友活动,活动规则如下:

小明会用红绳连接两名学生,被连中的两个学生将成为朋友。

小明想让所有学生都互相成为朋友,但是蓝桥幼儿园的学生实在太多了,他无法用肉眼判断某两个学生是否为朋友。于是他起来了作为编程大师的你,请你帮忙写程序判断某两个学生是否为朋友(默认自己和自己也是朋友)。

输入描述

第 1 行包含两个正整数 N,M,其中 N 表示蓝桥幼儿园的学生数量,学生的编号分别为 1∼N。

之后的第 2∼M+1 行每行输入三个整数,op,x,y:

  • 如果 op=1,表示小明用红绳连接了学生 x 和学生 y 。
  • 如op=2,请你回答小明学生 x 和 学生 y 是否为朋友。

1≤N,M≤2×105,1≤x,y≤N。

输出描述

对于每个 op=2 的输入,如果 x 和 y 是朋友,则输出一行 YES,否则输出一行 NO

输入输出样例

示例 1

输入

5 5 
2 1 2
1 1 3
2 1 3
1 2 3 
2 1 2

输出

NO
YES
YES

#include <iostream>
using namespace std;
int n,m;
int rel[200005]; 
int find(int x){
	if(rel[x]==x) return x;
	return rel[x]=find(rel[x]);
}
void jiaru(int x,int y){
	int x1=find(x);
	int y1=find(y);
	if(x1!=y1){
		rel[x1]=y1;
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		rel[i]=i;
	}
	for(int i=1;i<=m;i++){
		int op,x,y;
		cin>>op>>x>>y;
		if(op==1){
			jiaru(x,y);
		}else{
			if(find(x)==find(y)){
				cout<<"YES"<<endl;
			}else{
				cout<<"NO"<<endl;
			}
		}
	}
	return 0;
}

 H:::::::::::::::::蓝桥幼儿园(并查集)

题目描述

小明在练习绝世武功, n 个练功桩排成一排,一开始每个桩的损伤为 0。

接下来小明会练习 m 种绝世武功,每种武功都会对 [l,r] 区间分别造成 [s,e] 的伤害。

这个伤害是一个等差序列。例如 l=1,r=4,s=2,e=8 ,则会对 1−4 号练功桩造成2,4,6,8 点损伤。

小明想让你统计一下所有练功桩的损伤的和。

输入描述

第一行输入 n,m,代表练功桩的数量和绝世武功的种类数。

接下来 m 行输入 4 个整数 l,r,s,e 。

1≤n≤107,1≤m≤3×105,1≤l,r≤n

输出描述

输出一个整数代表所有练功桩的损伤和, 题目保证所有输入输出都在 [[0,9×1018]

输入输出样例

示例 1

输入

6 2
1 5 2 10
2 4 1 1

输出

33

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 512M

#include<iostream>
using namespace std;
 
//绝世武功(二阶差分数组)
typedef long long ll;
ll n,m,d,ans;//d:[s,e]公差
ll a[10000005],d1[10000005],d2[10000005];
//一阶差分数组d1,二阶差分数组d2
int main()
{
    cin>>n>>m;
    for(int i=1;i<=m;i++){
       ll l,r,s,e;
       cin>>l>>r>>s>>e;
       d=(e-s)/(r-l);//求出公差
       d2[l]= d2[l]+s;
       d2[l+1]=d2[l+1]+d-s;
       d2[r+1]=d2[r+1]-d-e;
       d2[r+2]=d2[r+2]+e;
    }
    for(int i=1;i<=n;i++){
        d1[i]=d1[i-1]+d2[i];
        a[i]=a[i-1]+d1[i];
        ans+=a[i];
    }
    cout<<ans<<endl;
    return 0;
}

 I:::::::::::::::::蓝桥侦探(种类并查集)

题目描述

小明是蓝桥王国的侦探。

这天,他接收到一个任务,任务的名字叫分辨是非,具体如下:

蓝桥皇宫的国宝被人偷了,犯罪嫌疑人锁定在 N 个大臣之中,他们的编号分别为 1∼N。

在案发时这 N 个大臣要么在大厅1,要么在大厅2,但具体在哪个大厅他们也不记得了。

审讯完他们之后,小明把他们的提供的信息按顺序记了下来,一共 M条,形式如下:

  • x y,表示大臣 xx 提供的信息,信息内容为:案发时他和大臣 y不在一个大厅。

小明喜欢按顺序读信息,他会根据信息内容尽可能对案发时大臣的位置进行编排。

他推理得出第一个与先前信息产生矛盾的信息提出者就是偷窃者,但推理的过程已经耗费了他全部的脑力,他筋疲力尽的睡了过去。作为他的侦探助手,请你帮助他找出偷窃者!

输入描述

第 1 行包含两个正整数 N,M,分别表示大臣的数量和口供的数量。

之后的第 2∼M+1 行每行输入两个整数 x,y,表示口供的信息。

1≤N,M≤5×105,1≤x,y≤N。

输出描述

输出仅一行,包含一个正整数,表示偷窃者的编号。

输入输出样例

示例 1

输入

4 5 
1 2
1 3 
2 3 
3 4
1 4

输出

2

运行限制

  • 最大运行时间:1s
  • 最大运行内存: 256M
#include <iostream>
using namespace std;
int n,m;
int ans;
int a[10000005];
int find(int x){
	if(a[x]==x) return x;
	return a[x]=find(a[x]);
}
void jiaru(int x,int y){
	int tx=find(x);
	int ty=find(y);
	if(tx!=ty){
		a[tx]=ty;
	}
}
int main(){
	cin>>n>>m;
	for(int i=1;i<=2*n;i++){
		a[i]=i;
	}
	for(int i=1;i<=m;i++){
		int x,y;
		cin>>x>>y;
		if(ans){
			break;
		}
		if(find(x)==find(y)||find(x+n)==find(y+n)){
			ans=x;
		}
		jiaru(x,y+n);
		jiaru(y,x+n); 
	}
	cout<<ans;
	return 0;
} 

 J:::::::::::::::::最长公共子序列(LCS)

题目描述

给定一个长度为 N 数组 a 和一个长度为 M 的数组 b。

请你求出它们的最长公共子序列长度为多少。

输入描述

输入第一行包含两个整数 N,M,分别表示数组 a 和 b 的长度。

第二行包含 N 个整数 a1​,a2​,...,an​。

第三行包含 M 个整数b1​,b2​,...,bn​。

1≤N,M≤103,1≤ai​,bi​≤109。

输出描述

输出一行整数表示答案。

输入输出样例

示例 1

输入

5 6
1 2 3 4 5
2 3 2 1 4 5

输出

4
#include <iostream>
#include <cmath>
using namespace std;
long long a[1005];
long long b[1005]; 
int n,m;
long long dp[1005][1005];
int main(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int j=1;j<=m;j++){
		cin>>b[j];
	}
	for(int i=1;i<=n;i++){
		for(int j=1;j<=m;j++){
			if(a[i]==b[j]){
				dp[i][j]=dp[i-1][j-1]+1;
			}else{
				dp[i][j]=max(dp[i-1][j],dp[i][j-1]);
			}
		}
	}
	cout<<dp[n][m];
	return 0;
}

 K:::::::::::::::::123(前缀和)

题目描述

小蓝发现了一个有趣的数列,这个数列的前几项如下:

1,1,2,1,2,3,1,2,3,4,⋯

小蓝发现,这个数列前 11 项是整数 1,接下来 2 项是整数 1 至 2,接下来 3 项是整数 1 至 3,接下来 4 项是整数 1 至 4,依次类推。

小蓝想知道,这个数列中,连续一段的和是多少。

输入描述

输入的第一行包含一个整数 T,表示询问的个数。

接下来 T 行,每行包含一组询问,其中第 ii 行包含两个整数 li​ 和 ri​,表示询问数列中第 li​ 个数到第 ri​ 个数的和。

输出描述

输出 T 行,每行包含一个整数表示对应询问的答案。

输入输出样例

示例

输入

3
1 1
1 3
5 8

输出

1
4
8

 

#include <iostream>
using namespace std;
int t; 
long long sum1[1500000]; 
long long qiuhe(long long x) {
	return (1+x)*x/2;
}


long long sum(long long x){
	if(x==0) return 0;
	long long l=0,r=1500000;
	while(r>=l){
		long long mid=(l+r)>>1;
		if(qiuhe(mid)>x){
			r=mid-1;
		}else{
			l=mid+1;
		}
	}
	return sum1[r]+qiuhe(x-qiuhe(r));
	
}
int main(){
	cin>>t;
	long long c,len=0;   
	
	for(long long i=1;len<=1e12;i++){
		sum1[i]=sum1[i-1]+qiuhe(i);    
		len+=i;
//		c=i;
	}
//	cout<<c;   c=1414214行 
	for(int i=0;i<t;i++){
		long long l,r;
		cin>>l>>r;
		cout<<sum(r)-sum(l-1)<<endl;
	}
	return 0;
}

 K:::::::::::::::::美丽的区间(尺取法)

题目描述

给定一个长度为 n 的序列 a1​,a2​,⋯,an​ 和一个常数 S。

对于一个连续区间如果它的区间和大于或等于 S,则称它为美丽的区间。

对于一个美丽的区间,如果其区间长度越短,它就越美丽。

请你从序列中找出最美丽的区间​。

输入描述

第一行包含两个整数 n,S,其含义如题所述。

接下来一行包含 n 个整数,分别表示a1​,a2​,⋯,an​。

0≤N≤105,1×ai​≤104,1≤S≤108。

输出描述

输出共一行,包含一个整数,表示最美丽的区间的长度。

若不存在任何美丽的区间,则输出 0。

输入输出样例

示例 1

输入

5 6
1 2 3 4 5

输出

2
#include <iostream>
using namespace std;
int n,s;
int a[1000005];
int ans=1e9;
int main(){
	cin>>n>>s;
	for(int i=0;i<n;i++){
		cin>>a[i];
	}
	int l=0,r=0;
	int m=0;
	while(r<n){
		if(m<s){
      m=m+a[r];
			r++;
		}else if(m>=s){
			ans=min(ans,r-l);
			m=m-a[l];
			l++;
		}
	}
  if(ans==1e9){
    cout<<0;
    return 0;
  }
	cout<<ans;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/m0_73731708/article/details/129722519
今日推荐