暴力方法就不说了 线段树正解真的考验思维 看了几个小时才大致明白..

就不说自己思路了.. 只附上参考的博客

看完题解觉得有两个重点 一是理解线段树里维护的是什么 二是理解判断x y的那三个if else(见代码) 上面两个博客都有提

 

 

#include <bits/stdc++.h>
using namespace std;

struct node
{
int l;
int r;
int val;
int tot;
int laz;
};

node tree[200010];
int pos[50010],book[50010];
int n,ans;

void pushup(int cur)
{
tree[cur].val=min(tree[2*cur].val,tree[2*cur+1].val);
tree[cur].tot=0;
if(tree[cur].val==tree[2*cur].val) tree[cur].tot+=tree[2*cur].tot;
if(tree[cur].val==tree[2*cur+1].val) tree[cur].tot+=tree[2*cur+1].tot;
return;
}

void pushdown(int cur)
{
if(tree[cur].laz!=0)
{
tree[2*cur].val+=tree[cur].laz;
tree[2*cur].laz+=tree[cur].laz;
tree[2*cur+1].val+=tree[cur].laz;
tree[2*cur+1].laz+=tree[cur].laz;
tree[cur].laz=0;
}
return;
}

void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
tree[cur].tot=r-l+1;
tree[cur].laz=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
return;
}

void update(int pl,int pr,int val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].val+=val;
tree[cur].laz+=val;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) update(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) update(pl,pr,val,2*cur+1);
pushup(cur);
return;
}

void query(int pl,int pr,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
if(tree[cur].val==1)
{
ans+=tree[cur].tot;
}
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) query(pl,pr,2*cur);
if(pr>=tree[2*cur+1].l) query(pl,pr,2*cur+1);
return;
}

int main()
{
int i,t,x,y;
while(scanf("%d",&n)!=EOF)
{
build(1,n,1);
memset(pos,0,sizeof(pos));
for(i=1;i<=n;i++)
{
scanf("%d",&t);
pos[t]=i;
}
memset(book,0,sizeof(book));
ans=0;
for(i=n;i>=1;i--)
{
book[pos[i]]=i;
x=book[pos[i]-1],y=book[pos[i]+1];
if(x>y) swap(x,y);
if(x>0&&y>0)
{
update(i,x-1,1,1);
update(y,n,-1,1);
}
else if(y>0)
{
update(i,y-1,1,1);
}
else
{
update(i,n,1,1);
}
query(i,n,1);
}
printf("%d\n",ans);
}
return 0;
}