NOIP提高组1890~1900集合答案(之前的文章标题错了,应该是1820开始的,不是1520开始的)

1890:【15NOIP提高组】跳石头

时间限制: 1000 ms         内存限制: 131072 KB
提交数: 1037     通过数: 561 

【题目描述】
这项比赛将在一条笔直的河道中进行,河道中分布着一些巨大岩石。组委会已经选择好了两块岩石作为比赛起点和终点。在起点和终点之间,有 N块岩石(不含起点和终点的岩石)。在比赛过程中,选手们将从起点出发,每一步跳向相邻的岩石,直至到达终点。

为了提高比赛难度,组委会计划移走一些岩石,使得选手们在比赛过程中的最短跳 跃距离尽可能长。由于预算限制,组委会至多从起点和终点之间移走M块岩石(不能 移走起点和终点的岩石)。

【输入】
一行包含三个整数 L,N,M,分别表示起点到终点的距离,起点和终 点之间的岩石数,以及组委会至多移走的岩石数。

接下来N行,每行一个整数,第i行的整数 Di(0 < Di < L)表示第i块岩石与起点的距离。这些岩石按与起点距离从小到大的顺序给出,且不会有两个岩石出现在同一个位置。

【输出】
只包含一个整数,即最短跳跃距离的最大值。

【输入样例】
25 5 2 
2
11
14
17 
21
【输出样例】
4
【提示】
输入输出样例1说明:将与起点距离为2和14的两个岩石移走后,最短的跳跃距离为4(从与起点距离17的岩石跳到距离21的岩石,或者从距离21的岩石跳到终点)。

其它输入输出样例下载

数据范围:

对于20%的数据,0 ≤ M ≤ N ≤ 10。 

对于50%的数据,0 ≤ M ≤ N ≤ 100。

对于100%的数据,0 ≤ M ≤ N ≤ 50,000,1 ≤ L ≤ 1,000,000,000。
#include<iostream>
#include<cstdio>
using namespace std;
int leng,n,m,a[50002];
bool check(int x){
	int last=0;
	int sum=0;
	for(int i=1;i<=n;i++){
		if(a[i]-last>=x){
			last=a[i];
		}else{
			sum++;
		}
	}
	if(leng-last<x){
		sum++;
	}
	return sum<=m;
}
int main(){
	cin>>leng>>n>>m;
	int l=1,r=leng;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	while(r>l){
		int mid=(l+r+1)>>1;
		if(check(mid)){               
			l=mid;
		}else{
			r=mid-1;
		}
	}
	cout<<l;
	return 0;
}
1891:【15NOIP提高组】子串

时间限制: 1000 ms         内存限制: 131072 KB
提交数: 244     通过数: 136 

【题目描述】
有两个仅包含小写英文字母的字符串AA和BB。现在要从字符串AA中取出kk个互不重叠的非空子串,然后把这kk个子串按照其在字符串AA中出现的顺序依次连接起来得到一个新的字符串,请问有多少种方案可以使得这个新串与字符串BB相等?注意:子串取出的位置不同也认为是不同的方案。

【输入】
第一行是三个正整数 n,m,kn,m,k,分别表示字符串AA的长度,字符串BB的长度,以及问题描述中所提到的kk,每两个整数之间用一个空格隔开。 第二行包含一个长度为nn的字符串,表示字符串 AA。第三行包含一个长度为mm的字符串,表示字符串BB。

【输出】
输出共一行,包含一个整数,表示所求方案数。由于答案可能很大,所以这里要求输出答案对 1,000,000,0071,000,000,007 取模的结果。

【输入样例】
6 3 1 
aabaab 
aab
【输出样例】
2
【提示】
样例2:

输入:

6 3 2 
aabaab 
aab
输出:

7
样例3:

输入:

6 3 3 
aabaab 
aab
输出:

7
输入输出样例说明:

所有合法方案如下:(加下划线的部分表示取出的子串)



其它输入输出样例下载

数据规模与约定:

对于第1组数据:1≤n≤500,1≤m≤50,k=11≤n≤500,1≤m≤50,k=1;

对于第2组至第3组数据:1≤n≤500,1≤m≤50,k=21≤n≤500,1≤m≤50,k=2;

对于第4组至第5组数据:1≤n≤500,1≤m≤50,k=m1≤n≤500,1≤m≤50,k=m;

对于第1组至第7组数据:1≤n≤500,1≤m≤50,1≤k≤m1≤n≤500,1≤m≤50,1≤k≤m;

对于第1组至第9组数据:1≤n≤1000,1≤m≤100,1≤k≤m1≤n≤1000,1≤m≤100,1≤k≤m;

对于所有10组数据:1≤n≤1000,1≤m≤200,1≤k≤m1≤n≤1000,1≤m≤200,1≤k≤m。
#include<cstdio>
#include<cstring>
#include<algorithm>
#define P 1000000007
using namespace std;
int n,m,K,t=1;
int f[2][205][205][2];
char A[1005],B[205];
int add(int x,int y)  {return x+y>=P?x+y-P:x+y;}
int dec(int x,int y)  {return x-y< 0?x-y+P:x-y;}
int mul(int x,int y)  {return 1ll*x*y%P;}
int main(){
	scanf("%d%d%d",&n,&m,&K);
	scanf("%s%s",A+1,B+1);
	f[0][0][0][0]=1;
	for(int i=1;i<=n;++i){
		f[t][0][0][0]=1;
		for(int j=1;j<=m;++j){
			for(int k=1;k<=m;++k){
				f[t][j][k][0]=add(f[t^1][j][k][0],f[t^1][j][k][1]);
				f[t][j][k][1]=(A[i]==B[j])?add(add(f[t^1][j-1][k][1],f[t^1][j-1][k-1][1]),f[t^1][j-1][k-1][0]):0;
			}
		}
		t^=1;
	}
	printf("%d\n",add(f[t^1][m][K][0],f[t^1][m][K][1]));
	return 0;
}
1892:【15NOIP提高组】运输计划

时间限制: 1000 ms         内存限制: 262144 KB
提交数: 614     通过数: 100 

【题目描述】
公元2044年,人类进入了宇宙纪元。

L国有n个星球,还有n-1条双向航道,每条航道建立在两个星球之间,这n-1条航道连通了L国的所有星球。

小P掌管一家物流公司,该公司有很多个运输计划,每个运输计划形如:有一艘物流飞船需要从ui号星球沿最快的宇航路径飞行到vi号星球去。显然,飞船驶过一条航道是需要时间的,对于航道j,任意飞船驶过它所花费的时间为tj,并且任意两艘飞船之间不会产生任何干扰。

为了鼓励科技创新,L国国王同意小P的物流公司参与L国的航道建设,即允许小P把某一条航道改造成虫洞,飞船驶过虫洞不消耗时间。

在虫洞的建设完成前小P的物流公司就预接了m个运输计划。在虫洞建设完成后, 这m个运输计划会同时开始,所有飞船一起出发。当这m个运输计划都完成时,小P的物流公司的阶段性工作就完成了。

如果小P可以自由选择将哪一条航道改造成虫洞,试求出小P的物流公司完成阶段性工作所需要的最短时间是多少?

【输入】
第一行包括两个正整数 n、m,表示L国中星球的数量及小P公司预接的运输计划的数量,星球从1到n编号。

接下来n-1行描述航道的建设情况,其中第i行包含三个整数ai,bi和ti,表示第i条双向航道修建在ai与bi两个星球之间,任意飞船驶过它所花费的时间为ti。接下来m行描述运输计划的情况,其中第j行包含两个正整数uj和vj,表示第j个运输计划是从 uj号星球飞往vj号星球。

【输出】
共1行,包含1个整数,表示小P的物流公司完成阶段性工作所需要的最短时间。

【输入样例】
6 3 
1 2 3 
1 6 4 
3 1 7 
4 3 6 
3 5 5 
3 6 
2 5 
4 5
【输出样例】
11

【提示】
输入输出样例1说明:

将第1条航道改造成虫洞:则三个计划耗时分别为:11、12、11,故需要花费的时间为12。

将第2条航道改造成虫洞:则三个计划耗时分别为:7、15、11,故需要花费的时间为15。

将第3条航道改造成虫洞:则三个计划耗时分别为:4、8、11,故需要花费的时间为11。

将第4条航道改造成虫洞:则三个计划耗时分别为:11、15、5,故需要花费的时间为15。

将第5条航道改造成虫洞:则三个计划耗时分别为:11、10、6,故需要花费的时间为11。

故将第3条或第5条航道改造成虫洞均可使得完成阶段性工作耗时最短,需要花费的时间为11。

其它输入输出样例下载

所有测试数据的范围和特点如下表所示:

对于100%的数据,100≤n≤300000,1≤m≤300000100≤n≤300000,1≤m≤300000。

请注意常数因子带来的程序效率上的影响。
#include<bits/stdc++.h>
using namespace std;
const int MAXN=300005;
int N,M,np=0,last[MAXN],dis[MAXN],dep[MAXN],size[MAXN],fa[MAXN],val[MAXN];
int dfs_clock=0,dfs_pos[MAXN],big_son[MAXN],top_node[MAXN];
int tot=0,root=0,lc[MAXN*2],rc[MAXN*2],MAX[MAXN*2],lazy[MAXN*2];
struct edge{int to,w,pre;}E[MAXN*2];
struct data{int l,r;};
data a[MAXN],k[MAXN];
 
bool cmp(data a,data b) {return a.l<b.l;}
 
char c;
void scan(int &x)
{
	for(c=getchar();c<'0'||c>'9';c=getchar());
	for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}
 
void addedge(int u,int v,int w)
{
	E[++np]=(edge){v,w,last[u]};
	last[u]=np;
}
 
void dfs1(int i)
{
	for(int p=last[i];p;p=E[p].pre)
	{
		int j=E[p].to;
		if(j==fa[i]) continue;
		
		fa[j]=i;
		dep[j]=dep[i]+1;
		dis[j]=dis[i]+E[p].w; 
		size[j]=1;
		val[j]=E[p].w;
		
		dfs1(j); 
		
		size[i]+=size[j];
		if(size[j]>size[big_son[i]]) big_son[i]=j;
	}
}
 
void dfs2(int i,int top)
{
	dfs_pos[i]=++dfs_clock;
	top_node[i]=top;
	if(!big_son[i]) return;
	dfs2(big_son[i],top);
	for(int p=last[i];p;p=E[p].pre)
	{
		int j=E[p].to;
		if(j==fa[i]||j==big_son[i]) continue;
		dfs2(j,j);
	}
}
 
int LCA(int u,int v)
{
	while(top_node[u]!=top_node[v])
	{
		if(dep[top_node[u]]<dep[top_node[v]]) swap(u,v);
		u=fa[top_node[u]];
	}
	if(dep[u]>dep[v]) swap(u,v);
	return u;
}
 
void build(int &now,int L,int R)
{
	if(!now) now=++tot;
	if(L==R) return;
	int mid=(L+R)/2;
	build(lc[now],L,mid);
	build(rc[now],mid+1,R);
}
 
void pushup(int now) {MAX[now]=max(MAX[lc[now]],MAX[rc[now]]);}
 
void pushdown(int now)
{
	if(!lazy[now]) return;
	int l=lc[now],r=rc[now],w=lazy[now];
	MAX[l]=max(MAX[l],w); lazy[l]=max(lazy[l],w);
	MAX[r]=max(MAX[r],w); lazy[r]=max(lazy[r],w);
	lazy[now]=0;
}
 
void update(int now,int L,int R,int i,int j,int w)
{
	if(j<i) return;
	if((i<=L)&&(R<=j))
	{
		MAX[now]=max(MAX[now],w);
		lazy[now]=max(lazy[now],w);
		return;
	}
	pushdown(now);
 
	int mid=(L+R)/2;	
	if(i<=mid) update(lc[now],L,mid,i,j,w);
	if(mid<j) update(rc[now],mid+1,R,i,j,w);
	pushup(now);
}
 
int query(int now,int L,int R,int pos)
{
	if(L==pos&&R==pos) return MAX[now];
	pushdown(now);
	int mid=(L+R)/2;
	if(pos<=mid) return query(lc[now],L,mid,pos);
	return query(rc[now],mid+1,R,pos);
}
 
void tree_up(int id,int w)
{
	int u=a[id].l,v=a[id].r,cnt=0;
	
	while(top_node[u]!=top_node[v])
	{
		if(dep[top_node[u]]<dep[top_node[v]]) swap(u,v);
		k[++cnt]=(data){dfs_pos[top_node[u]],dfs_pos[u]};
		u=fa[top_node[u]];
	}
	
	if(dep[u]>dep[v]) swap(u,v);
	k[++cnt]=(data){dfs_pos[u]+1,dfs_pos[v]}; //注意同一条链上的节点,深度小的不能更新 
	
	sort(k+1,k+1+cnt,cmp);
	
	if(k[1].l>1) update(root,1,N,1,k[1].l-1,w);  //特判1,N 
	if(k[cnt].r<N) update(root,1,N,k[cnt].r+1,N,w);
	
	
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值