对于数组的一些不错的微处理

Codeforces 873B - Balanced Substring(思维)
题目链接:http://codeforces.com/problemset/problem/873/B

题目大意:一个字符串全部由‘0’和‘1’组成,当一段区间[l,r]内的‘0’和‘1’个数相等,则称为平衡子串,求最长的平衡子串。

解题思路:将0换成-1,算出每个点的前缀和,若两个点前缀和相同,从第一个点到第二个点之前的字符串则为平衡串,求出最长的即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
const int N=1e5+5;
int Min[2*N];
int main()
{
	memset(Min,0x3f,sizeof(Min));
	int n;scanf("%d",&n);
	int ans=0,sum=N;
	getchar();
	Min[sum]=0;
	for(int i=1;i<=n;i++){
		char ch;
		scanf("%c",&ch);
		if(ch=='1'){
			sum++;
		}else{
			sum--;
		}
		Min[sum]=min(Min[sum],i);//tip1
		ans=max(ans,i-Min[sum]);
	}
	cout<<ans<<endl;
}

Tip1:很显然这里运用到了前缀和的思想,但是前缀和我们想找的是一开始的最小position,那就如代码这样处理,Min[sum]初始化为无限大,后来从i=1往上遍历,当前缀和值一样时,永远保留最小位置。而答案就是每次更新ans,保存最大ans输出即可。

Educational Codeforces Round 76(Rated for Div.2)
题目链接:https://codeforces.com/contest/1257/problem/C

题目大意:给你n个元素(每个元素大小为1~n),找到n出现频率最高的元素(即为统治数),然后找统治数位置间最小的差值并且输出。

#include<bits/stdc++.h>
using namespace std;
int a[200005];
int b[200005];
int main()
{
	int t;cin>>t;
	while(t--){
		memset(b,0,sizeof(b));
		int n;cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		int ans=n+1;
		for(int i=1;i<=n;i++){
			if(b[a[i]]){
				ans=min(ans,i+1-b[a[i]]);
			}
			b[a[i]]=i;
		}
		if(ans==n+1) ans=-1;
		cout<<ans<<endl;
	}
}

先初始化ans为足够大的数,然后依次遍历更新该数的位置,位置差就是当前的位置减去该数之前的位置,然后比较min,保存答案输出即可。

Codeforces 884C : Bertown Subway
题目链接:https://vjudge.net/contest/342431#problem/D
题目大意:找环,最后找出2个最大的环,答案就是最大的两个的和的平方再加上其他环自己的平方和。

#include<iostream>
#include<algorithm>
#include<cstring>
#include<vector>
#define ll long long
#define rep(i,a,n) for(int i=a;i<=n;i++)
#define per(i,n,a) for(int i=n;i>=a;i--)
#define endl '\n'
#define mem(a) memset(a,0,sizeof(a))
#define IO ios::sync_with_stdio(false);cin.tie(0);
using namespace std;
const int INF=0x3f3f3f3f;
const int mod=1e9+7;
const int N=1e5+5;
vector<ll> Q;
ll n,a[N],ans,book[N];
int main()
{
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	//找环过程↓*Tip
	for(int i=1;i<=n;i++){
		if(book[i]) continue;
		book[i]=1;
		int cnt=1,now=a[i];
		while(now!=i){
			book[now]=1;
			now=a[now];
			cnt++;
		}
		Q.push_back(cnt);
	}
	
	sort(Q.begin(),Q.end());
	if(Q.size()<2) ans=n*n;
	else{
		ans=(Q[Q.size()-1]+Q[Q.size()-2])*(Q[Q.size()-1]+Q[Q.size()-2]);
		for(int i=0;i<Q.size()-2;i++) ans+=Q[i]*Q[i];
	}
	cout<<ans<<endl;
}

Tip:他这个技巧比较高明,遇到某个元素直接把他的环全部挖出来了,对于每个position都有一个target对应,他利用新的target代替原来postion,再去找下一个target,因为是环嘛,所以最后的target会与初始的position一致的。环内每多一个元素,cnt++。

发布了71 篇原创文章 · 获赞 5 · 访问量 3402

猜你喜欢

转载自blog.csdn.net/Rainfoo/article/details/103083182
今日推荐