洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第1张图片

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第2张图片


 N<=1e5,基本上可以得出这道题算法复杂度如果在 O(n^2) 及以上都是过不了的,不过秉承着蓝桥杯是暴力杯的原则,可以从朴素算法一步一步开始做。

TLE代码  O(n^3)  朴素算法  60pts

#include 
using namespace std;
const int N=1e5+1;

int n,a[N],b[N],c[N];
long long ans;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL),cout.tie(NULL);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i)cin>>b[i];
	for(int i=1;i<=n;++i)cin>>c[i];
	
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j)
	for(int k=1;k<=n;++k)
	ans+=(a[i]

跟着题目模拟一遍,就拿到了7个样例点。有这还要什么自行车

这道题和a+b+c=d这种数对都存在共性,模拟的时候会发现第一列的数值被重复跑了n次

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第3张图片

即计算4的时候,1->3->4  ,  2->3->4,对于5来说也是,1->3->5  ,  2->3->5

前面两段被重复计算了,所以可以先算出中间那一列可以被连上的情况,减少重复计算。

TLE代码  O(n^2)  优化暴力  84pts

#include 
using namespace std;
const int N=1e5+1;

int n,a[N],b[N],c[N],cnt[N];
long long ans;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL),cout.tie(NULL);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>a[i];
	for(int i=1;i<=n;++i)cin>>b[i];
	for(int i=1;i<=n;++i)cin>>c[i];
	
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j)
	cnt[i]+=b[i]>a[j];
	
	for(int i=1;i<=n;++i)
	for(int j=1;j<=n;++j)
	if(c[j]>b[i])ans+=cnt[i];
	
	cout<

到这一步之后可以发现,暴力已经没什么地方可以优化了,只能从核心入手对公式进行整改。

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第4张图片

显然b序列5可以被a连上的所有情况是

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第5张图片

即累计在a序列中存在比b[1]小的数,那就直接累计比b[1]小的数出现的次数即可,将式子变为 

洛谷 P8667 [蓝桥杯 2018 省 B] 递增三元组_第6张图片

 遍历a序列用桶记录一下所有数出现的次数(哈希)即可解决问题,其中求和式子可以应用前缀和做到O(1)查询。

AC代码  O(n)  100pts

#include 
using namespace std;
const int N=1e5+1;

long long n,a[N],b[N],c[N],cnt[N],tmp,ans;

int main(){
	ios::sync_with_stdio(false);
	cin.tie(NULL),cout.tie(NULL);
	cin>>n;
	for(int i=1;i<=n;++i)cin>>tmp,a[tmp]++;
	for(int i=1;i<=n;++i)cin>>tmp,b[tmp]++;
	for(int i=1;i<=n;++i)cin>>tmp,c[tmp]++;
	
	for(int i=1;i

你可能感兴趣的:(洛谷,蓝桥杯,算法,枚举,c++,数据结构)