题目链接: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;
}