10.21T5 二分+线段树

Description

Input

6
10
3
7
4
12
2

Output

5
 
 
 
对每个位置二分后面的位置,找出恰好没有高于自己的点加起来就可以了,用线段树维护最大值
code:
 1 #include<iostream>
 2 #include<cstdio>
 3 #define N 1000005
 4 #define lc (p<<1)
 5 #define rc (p<<1|1)
 6 using namespace std;
 7 long long a[N];
 8 struct node{
 9     long long l,r,max;
10 }t[N];
11 void pushup(long long p){
12     t[p].max=max(t[lc].max,t[rc].max);
13 }
14 void build(long long p,long long l,long long r){
15     t[p].l=l,t[p].r=r;
16     if(l==r){
17         t[p].max=a[l];
18         return;
19     }
20     long long mid=l+r>>1;
21     build(lc,l,mid);
22     build(rc,mid+1,r);
23     pushup(p);
24 }
25 long long query(long long p,long long ql,long long qr){
26     if(ql<=t[p].l&&t[p].r<=qr){
27         return t[p].max;
28     }
29     long long ans=0;
30     long long mid=t[p].l+t[p].r>>1;
31     if(ql<=mid)ans=max(ans,query(lc,ql,qr));
32     if(qr>mid)ans=max(ans,query(rc,ql,qr));
33     return ans;
34 }
35 int main(){
36     long long n;
37     cin>>n;
38     for(long long i=1;i<=n;i++){
39         cin>>a[i];
40     }
41     build(1,1,n);
42     long long tot=0;
43     for(long long i=1;i<=n;i++){
44         long long l=i,r=n,ans=0;
45         while(l<=r){
46             long long mid=l+r>>1;
47             if(query(1,i+1,mid)<a[i])l=mid+1,ans=mid;
48             else r=mid-1;
49         }
50         tot+=ans-i;
51     }
52     cout<<tot;
53 }

over

posted @ 2018-10-21 20:28  saionjisekai  阅读(78)  评论(0编辑  收藏  举报