E2. Three Blocks Palindrome (hard version) (贪心&暴力)

E2. Three Blocks Palindrome (hard version) (贪心&暴力)

题目传送门

思路:对于数据较大情况,我们考虑要迅速找到区间 [ l , r ] [l,r] [l,r],显然第一个字符串的数字的个数和第三个字符串个数相同 ,要是区间 [ l , r ] [l,r] [l,r]中数的个数越多,我们只需要让 l l l越靠左, r r r越靠右,而 l , r l,r l,r的确定可以通过记录每个数字对于出现的位置(以空间换时间)。遍历第一个字符串的数字个数,最后取 m a x max max即可。

时间复杂度: O ( 200 × n ) O(200\times n) O(200×n)

AC代码:

#include<bits/stdc++.h>
using namespace std;
int main(){
	int t,n;
	scanf("%d",&t);
	while(t--){
		scanf("%d",&n);
		vector<vector<int> >a(201,vector<int>(n+1));
		vector<vector<int> >p(201);//储存每个数的位置. 
		for(int i=1,x;i<=n;i++)
		{
			scanf("%d",&x);
			for(int j=1;j<=200;j++) //前缀和 
				a[j][i]=a[j][i-1]+(x==j);
			p[x].push_back(i);
		}
		int ans=0;
		for(int k=1;k<=200;k++){ //O(n*200*200) 
				ans=max(ans,(int)p[k].size());//如果只取一个子串. 
			for(int i=1;i<=(p[k].size()/2);i++)//左右对称贪心思想. 
			{
				  int l=p[k][i-1]+1,r=p[k][p[k].size()-i]-1;//找到区间[l , r] 
				  for(int j=1;j<=200;j++) //取最大值. 
				  {
				  		int x=a[j][r]-a[j][l-1];
				  		ans=max(ans,i*2+x);
				  }
			}
		}
		printf("%d\n",ans);
	}
	return 0;
}
这段代码是一个区块链的实现中的获取最长链的函数,其主要思路是遍历所有区块,从每个区块出发,向前查找每个区块的前一个区块是否在当前区块链中存在,并且不是根节点'root'。如果找到了前一个区块,则将其加入到当前链表的头部。最终,如果当前链表的长度大于已经找到的最长链长度,则将当前链表作为最长链。 这个函数可能需要一些解释,下面是对代码每行的解释: 1. `longestChain () {`: 定义一个函数叫做`longestChain`。 2. `let longestChain = [];`: 初始化一个最长链为空数组。 3. `for (const [hash, block] of this.blocks) {`: 遍历所有区块,使用解构赋值获取当前区块的哈希值和区块本身。 4. `const chain = [block];`: 初始化一个当前链表,将当前区块加入其中。 5. `let previousBlock = block;`: 初始化一个前一个区块,将其赋值为当前区块。 6. `while (this.blocks.has(previousBlock.previousHash) && (this.blocks.has(previousBlock.previousHash)).has !== 'root') {`: 在当前区块链中查找前一个区块,如果找到且前一个区块不是根节点'root',则进入循环。 7. `previousBlock = this.blocks.get(previousBlock.previousHash);`: 将前一个区块作为当前区块,继续向前查找。 8. `chain.unshift(previousBlock);`: 将前一个区块加入到当前链表的头部。 9. `if (chain.length > longestChain.length) {`: 判断当前链表是否比已经找到的最长链更长。 10. `longestChain = chain;`: 如果当前链表更长,则将其作为最长链。 11. `console.log(longestChain)`: 输出最长链到控制台。 12. `return longestChain;`: 返回最长链。
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

酷酷的Herio

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值