ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

题目Luogu-P1311 选择客栈

2022-07-24 20:05:41  阅读:170  来源: 互联网

标签:int Luogu 客栈 st near MAXN P1311 define


题目链接

题目很好理解


1.暴力 60分

根据题面不难想到O(n2)的暴力,对b数组做一个最小值st表,然后暴力枚举两个端点,看区间最小值是否小于等于p即可

// Problem: P1311 [NOIP2011 提高组] 选择客栈
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1311
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 200050
#define MAXM 10003
using namespace std;
int n,k,p;
int a[MAXN],b[MAXN],st[MAXN][21];
int ask(int l,int r){
	int k=log2(r-l+1);
	return min(st[l][k],st[r-(1<<k)+1][k]);
}
int main(){
	cin>>n>>k>>p;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
		st[i][0]=b[i];
	}
	for(int j=1;j<=20;j++){
		for(int i=1;i+(1<<j)-1<=n;i++){
			st[i][j]=min(st[i][j-1],st[i+(1<<(j-1))][j-1]);
		}
	}
	int ans=0;
	for(int i=1;i<n;i++){
		for(int j=i+1;j<=n;j++){
			if(a[i]!=a[j])	continue;
			if(ask(i,j)>p)	continue;
			ans++;	
		}
	}
	cout<<ans;
	return 0;
}

2.玄学优化 ?分(写挂了)

观察暴力,发现有许多时候,枚举的右端点与左端点的a值不一样,所以想到用Map映射色调,然后用vector挂载,每个vector都是色调相同的客栈,无奈很难写,而且出题人可以用一组一个色调只有两个客栈的数据把它卡回O(n2)

程序略


3.递推 100分

可以从前往后依次加入客栈,考虑一下新加入一个客栈,对答案会有什么贡献

第一种情况,如果加入的客栈,b>p,那么这个客栈必须与它之前a值相同,且之间有b<p客栈的客栈组对贡献一对答案

第二种情况,如果加入的客栈,b<=p,那么这个客栈本身满足要求,所以与它之前任意a值相同的客栈,均可以组对贡献一对答案

一开始,想初始化出每一个点前面每一个色调的数量,但这样数组会开到105*105,开不下

其实没有必要存下所有的数量

我们设数组f[i]表示前i个客栈内的答案个数

用一个变量near,来表示在已经使用过的客栈过中,i最近的一个b<=p的客栈的下标。(可以是自己)

用一个数组num[i],表示色调i,在前near个客栈中出现的次数。

这样,在从f[i-1]更新f[i]的时候,如果 客栈i 本身bi<=p,那么先把从near到i所有的色调计入num数组,然后near=i,完成对near的维护

怎么计算f[i]呢?仔细思考,发现在更新完near之后,客栈i 一定能与客栈near前的客栈(包括客栈near配对),因为它们之间有符合bi<=p的客栈near,所以必定符合条件,而num的数量正是我们想要的,加上num[客栈i 的色调]即可

但是,如果 客栈i 自己符合条件,此时near已经被更新成 i ,加num之后还要减一,因为每个客栈是不能与自己配对的

程序很简单

// Problem: P1311 [NOIP2011 提高组] 选择客栈
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P1311
// Memory Limit: 125 MB
// Time Limit: 1000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include <bits/stdc++.h>
#define INF 0x7fffffff
#define MAXN 200050
#define MAXM 10003
using namespace std;
int n,k,p;
int a[MAXN],b[MAXN],st[MAXN][21];
int f[MAXN];
int num[MAXN];
int main(){
	cin>>n>>k>>p;
	for(int i=1;i<=n;i++){
		cin>>a[i]>>b[i];
	}
	int near=b[1]<=p?++num[a[1]]:0;
	for(int i=2;i<=n;i++){
		if(b[i]<=p){
			for(int j=near+1;j<=i;j++){
				num[a[j]]++;
			}
			near=i;
			f[i]=f[i-1]+num[a[i]]-1;
		}else{
			f[i]=f[i-1]+num[a[i]];
		}
	}
	cout<<f[n];
	return 0;
}

AC

标签:int,Luogu,客栈,st,near,MAXN,P1311,define
来源: https://www.cnblogs.com/XHZS-XY/p/16515299.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有