zoukankan      html  css  js  c++  java
  • BZOJ4059[Cerc2012]Non-boring sequences(扫描线/分治)

    这题正解应该是扫描线,就是发现DP的区间在两个维度都为连续段,于是可以直接扫描线。但不幸的是,扫描线常数过大,无法通过本题。

    考虑分治。对于分治区间[l,r],可以记录pre和nxt表示其前/后一次出现的位置,每当遇到一个出现次数=1的数,可以直接把区间分为两半判断,反之则丢掉这个数,而仅会分治一次,且掐断地方是先判两边,复杂度近似O(nlogn)。

    实在太坑了,其实是一道练习扫描线的好题qwq

    #include<cstdio>
    #include<algorithm>
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    using namespace std;
    const int N=2e5+7;
    typedef long long ll;
    struct line{int x,l,r,v;}c[N<<1];
    int n,m,a[N],b[N],L[N],R[N],pre[N],sum[N<<2],cnt[N<<2];
    bool cmp(line a,line b){return a.x<b.x;}
    void insert(int a1,int a2,int b1,int b2)
    {c[++m]=(line){a1,b1,b2,1},c[++m]=(line){a2+1,b1,b2,-1};}
    void build(int l,int r,int rt)
    {
        sum[rt]=cnt[rt]=0;
        if(l==r)return;
        int mid=l+r>>1;
        build(lson),build(rson);
    }
    void pushup(int l,int r,int rt)
    {
        if(cnt[rt])sum[rt]=r-l+1;
        else if(l==r)sum[rt]=0;
        else sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    }
    void update(int L,int R,int v,int l,int r,int rt)
    {
        if(L<=l&&r<=R){cnt[rt]+=v,pushup(l,r,rt);return;}
        int mid=l+r>>1;
        if(L<=mid)update(L,R,v,lson);
        if(R>mid)update(L,R,v,rson);
        pushup(l,r,rt);
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            scanf("%d",&n);
            build(1,n,1);
            for(int i=1;i<=n;i++)scanf("%d",&a[i]),b[i]=a[i];
            sort(b+1,b+n+1);
            m=unique(b+1,b+n+1)-b-1;
            for(int i=1;i<=n;i++)a[i]=lower_bound(b+1,b+m+1,a[i])-b;
            m=0;
            for(int i=1;i<=n;i++)pre[i]=0;
            for(int i=1;i<=n;i++)L[i]=pre[a[i]],pre[a[i]]=i;
            for(int i=1;i<=n;i++)pre[i]=n+1;
            for(int i=n;i;i--)R[i]=pre[a[i]],pre[a[i]]=i;
            for(int i=1;i<=n;i++)insert(L[i]+1,i,i,R[i]-1);
            sort(c+1,c+m+1,cmp);
            ll ans=0;
            for(int i=1,p=0;i<=n;i++)
            {
                while(p<m&&c[p+1].x==i)p++,update(c[p].l,c[p].r,c[p].v,1,n,1);
                ans+=sum[1];
            }
            if(ans==1ll*n*(n+1)/2)puts("non-boring");
            else puts("boring");
        }
    }
    扫描线的TLE代码
    #include<cstdio>
    #include<algorithm>
    #include<map>
    using namespace std;
    const int N=2e5+7;
    int n,m,a[N],pre[N],nxt[N];
    map<int,int>lst;
    bool solve(int l,int r)
    {
        if(l>=r)return 1;
        int p=l,q=r;
        while(p<=q)
        {
            if(pre[p]<l&&nxt[p]>r)return solve(l,p-1)&&solve(p+1,r);p++;
            if(pre[q]<l&&nxt[q]>r)return solve(l,q-1)&&solve(q+1,r);q--;
        }
        return 0;
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            lst.clear();
            scanf("%d",&n);
            for(int i=1,pos;i<=n;i++)scanf("%d",&a[i]),pos=lst[a[i]],nxt[pos]=i,pre[i]=pos,lst[a[i]]=i;
            for(int i=1;i<=n;i++)nxt[lst[a[i]]]=n+1;
            if(solve(1,n))puts("non-boring");else puts("boring");
        }
    }
    分治的AC代码
  • 相关阅读:
    TransactionScop事务机制的使用
    MVC无刷新上传图片并显示
    WebClient和WebRequest获取html代码
    Web.config配置详解
    分类和扩展有什么区别?可以分别用来做什么?分类有哪些局限性?分类的结构体里面有哪些成员?
    有序二维数组的查找
    生成Excel.xlsx文件 iOS
    charles Https抓包
    https 通信流程和Charles 抓包原理
    fastlane自动化打包ipa并发布到firim或者蒲公英
  • 原文地址:https://www.cnblogs.com/hfctf0210/p/10945753.html
Copyright © 2011-2022 走看看