zoukankan      html  css  js  c++  java
  • 51nod 1810 连续区间

    感觉跟中位数那题很像啊,不过简单一点还是不会

    大力分治,那么要求的就是左端点在左区间,右端点在右区间的满足是一个连续排列的数量

    对于一个连续的排列(设i是左端点j是右端点),有max-min+1=j-i+1

    那么分情况讨论

    枚举其中一个端点,若max,min都在这一边,那么可以计算另一端的端点

    否则有两个条件:mx[i]>mx[j]&&mn[i]>mn[j](mx在左mn在右,反过来也是类似的)考虑mx单调增,mn单调减,用两个指针扫描,对于j的延伸,mn一定满足条件,只需要判断mx是否满足。对于i的延伸,mx一定满足条件,只需要判断mn是否满足。

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    
    #define v(i) v[i+1000010]
    using namespace std;
    typedef long long LL;
    
    int a[1100000],mx[1100000],mn[1100000];LL ans;
    int v[3100000];
    void solve(int l,int r)
    {
        if(l==r){ans++;return ;}
        int mid=(l+r)/2;
        solve(l,mid),solve(mid+1,r);
        
        mx[mid]=mn[mid]=a[mid];
        for(int i=mid-1;i>=l;i--)
            mx[i]=max(mx[i+1],a[i]), mn[i]=min(mn[i+1],a[i]);
        mx[mid+1]=mn[mid+1]=a[mid+1];
        for(int j=mid+2;j<=r;j++)
            mx[j]=max(mx[j-1],a[j]), mn[j]=min(mn[j-1],a[j]);
            
        for(int i=mid;i>=l;i--)
        {
            int L=mx[i]-mn[i]+1;
            int j=i+L-1;
            if(mid+1<=j&&j<=r&&mx[i]>mx[j]&&mn[i]<mn[j])ans++;
        }
        for(int j=mid+1;j<=r;j++)
        {
            int L=mx[j]-mn[j]+1;
            int i=j-L+1;
            if(l<=i&&i<=mid&&mx[j]>mx[i]&&mn[j]<mn[i])ans++;
        }
        
        int h=mid+1,t=mid+1;//mx在左,mn在右 
        for(int i=mid;i>=l;i--)
        {
            while(t<=r&&mx[i]>mx[t])v(mn[t]+t)++,t++;
            while(h<t&&mn[i]<mn[h])v(mn[h]+h)--,h++;
            ans+=v(mx[i]+i);
        }
        while(h<t)v(mn[h]+h)--,h++;
        
        h=mid,t=mid;
        for(int j=mid+1;j<=r;j++)
        {
            while(t>=l&&mx[j]>mx[t])v(mn[t]-t)++,t--;
            while(h>t&&mn[j]<mn[h])v(mn[h]-h)--,h--;
            ans+=v(mx[j]-j);
        }
        while(h>t)v(mn[h]-h)--,h--;
    }
    int main()
    {
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i]);
        ans=0;solve(1,n);
        printf("%lld
    ",ans);
        return 0;
    }
  • 相关阅读:
    20190922 模拟
    poj3417 Network/闇の連鎖[树上差分]
    poj3280 Cheapest Palindrome[区间DP]
    poj3691 DNA repair[DP+AC自动机]
    BZOJ1030 [JSOI2007]文本生成器[DP+AC自动机]
    loj2424 「NOIP2015」子串[字符串DP]
    poj1038 Bugs Integrated, Inc.[状压DP]
    第05组 Beta冲刺 (2/5)(组长)
    第05组 Beta冲刺 (1/5)(组长)
    第05组 Alpha冲刺 总结(组长)
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/9814355.html
Copyright © 2011-2022 走看看