Educational Codeforces Round 64 (Rated for Div. 2) E. Special Segments of Permutation(启发式合并)

题目链接:http://codeforces.com/contest/1156/problem/E

启发式合并的题目,好久没碰到了,看了题解才会啊?

预处理每个值作为最大值的区间,然后扫短的区间,查另一个端点落不落在长区间内就好了

 

代码:

#include
#define xx first
#define yy second
#define mp make_pair
#define pb push_back
using namespace std;
typedef long long ll;
typedef pair pii;
const int MAXN=2e5+5;
const int INF=1e9;
int L[MAXN],R[MAXN],p[MAXN],pos[MAXN];
stack st;
ll calc(int l,int r,int pl,int pr,int mx)
{
	ll ret=0;
	for(int i=l;i<=r;i++)
	{
		if(pos[mx-p[i]]>=pl&&pos[mx-p[i]]<=pr)
			ret++;
	}
	return ret;
}
int main()
{
	//freopen("in.txt","r",stdin);
	//freopen("out.txt","w",stdout);
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&p[i]);
		pos[p[i]]=i;
	}
	p[0]=p[n+1]=INF;
	st.push(0);
	for(int i=1;i<=n;i++)
	{
		while(p[i]>p[st.top()]) st.pop();
		L[i]=st.top();
		st.push(i);
	}
	while(!st.empty()) st.pop();
	st.push(n+1);
	for(int i=n;i>=1;i--)
	{
		while(p[i]>p[st.top()]) st.pop();
		R[i]=st.top();
		st.push(i);
	}
	ll ans=0;
	for(int i=1;i<=n;i++)
	{
		int lenL=i-L[i];
		int lenR=R[i]-i;
		if(lenL>lenR)
			ans+=calc(i+1,R[i]-1,L[i]+1,i-1,p[i]);
		else
			ans+=calc(L[i]+1,i-1,i+1,R[i]-1,p[i]);
	}
	printf("%lld\n",ans);
	return 0;
}

 

你可能感兴趣的:(codeforces)