• bzoj4358: permu


    终于又可以好好学习了?雾zzzz

    开始写了一发KDT,做法就是把询问看成二维坐标点,然后按大小顺序插入每一个数字,包含它的区间计数器+1,否则归零

    那么答案就是历史最大值

    看起来很好写??(雾)

    这个东西的标记。。。。呵呵呵。。。

    Rose巨神告诉我要用到历史最值线段树相关打标记的方法。。。。orz了吉司机很久然而还没有写出来。。。

     

    换个做法。。也是带根号的莫队

    对于每个位置维护在值域中向左右的最大连续长度,每次加入一个数,通过它值域左右的数可以得到更新,然后它不需要把包含它的那连续一整段全部更新,只需要更新这一段的边界点即可

    先将左端点分块,一个块中的询问按右端点排序,对于非当前块的数,因为右端点递增相当于扫一次,当前块的每次暴力算一次,然后清空即可

    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    
    int c[51000];
    int block,st[51000];
    struct query{int l,r,id;}q[51000];int as[51000];
    bool cmp(query q1,query q2){return st[q1.l]==st[q2.l]?q1.r<q2.r:st[q1.l]<st[q2.l];}
    
    int L[51000],R[51000];
    int top,Lid[51000],Rid[51000],Ld[51000],Rd[51000];
    void push(int ll,int rr)
    {
        top++;
        Lid[top]=ll,Ld[top]=L[ll];
        Rid[top]=rr,Rd[top]=R[rr];
    }
    void pop()
    {    
        while(top>0)
        {
            L[Lid[top]]=Ld[top];
            R[Rid[top]]=Rd[top];
            top--;
        }
    }
    int main()
    {
        freopen("a.in","r",stdin);
        freopen("a.out","w",stdout);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)scanf("%d",&c[i]);
        for(int i=1;i<=m;i++)
            scanf("%d%d",&q[i].l,&q[i].r),q[i].id=i;
            
        block=int(sqrt(double(n+1)))+1;
        for(int i=1;i<=n;i++)st[i]=(i-1)/block+1;
        sort(q+1,q+m+1,cmp);
        
        int las=1;
        for(int b=1;b<=block;b++)
        {
            int mmax=0,r=b*block;
            memset(L,0,sizeof(L));
            memset(R,0,sizeof(R));
            for(int i=las;st[q[i].l]==b&&i<=m;i++,las=i)
            {
                while(q[i].r>r)
                {
                    r++;
                    L[c[r]]=L[c[r]-1]+1;
                    R[c[r]]=R[c[r]+1]+1;
                    
                    int d=L[c[r]]+R[c[r]]-1;
                    L[c[r]+R[c[r]]-1]=d;
                    R[c[r]-L[c[r]]+1]=d;
                    mmax=max(mmax,d);
                }
                
                as[q[i].id]=mmax;
                int li=min(q[i].r,b*block);
                for(int j=q[i].l;j<=li;j++)
                {
                    L[c[j]]=L[c[j]-1]+1;
                    R[c[j]]=R[c[j]+1]+1;
                    
                    int d=L[c[j]]+R[c[j]]-1;
                    int ll=c[j]+R[c[j]]-1,rr=c[j]-L[c[j]]+1;
                    push(ll,rr);
                    L[ll]=d;
                    R[rr]=d;
                    as[q[i].id]=max(as[q[i].id],d);
                }
                
                pop();
                for(int j=q[i].l;j<=li;j++)L[c[j]]=R[c[j]]=0;
            }
        }
        
        for(int i=1;i<=m;i++)printf("%d
    ",as[i]);
        return 0;
    }
  • 相关阅读:
    golang 内存模型
    go-设计思想
    扁平化团队的实质
    技术团队的管理体系
    技术团队的目标管理
    从0到1打造直播 App
    管理你的项目
    JavaEE开发基础
    Java调优知识汇总
    从技术走向管理读书笔记
  • 原文地址:https://www.cnblogs.com/AKCqhzdy/p/10233787.html
Copyright © 2020-2023  润新知