• BZOJ 3809 Gty的二逼妹子序列


    暴力。。。严格的说是mlogn+m√nlogn的。。。就是莫队+BIT。

    然后我们可以按照值域分块,这样修改O(1)查询O(√n),这样总复杂度就是2*m*√n。

    有点像做了一个时间复杂度的权衡。。。看起来查询变慢了,事实上总复杂度是变快了。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #define maxn 100050
    #define maxm 1000050
    using namespace std;
    int n,m,len=300,blo[maxn],st[maxn],ret=0,val[maxn],cnt[maxn],a[maxn],ans[maxm],p1,p2;
    int a1,a2,a3,a4;
    struct query
    {
        int l,r,a,b,id;
        query (int l,int r,int a,int b,int id):l(l),r(r),a(a),b(b),id(id) {}
        query () {}
    }q[maxm];
    int read()
    {
        char ch;int data=0;
        while (ch<'0' || ch>'9') ch=getchar();
        while (ch>='0' && ch<='9')
        {
            data=data*10+ch-'0';
            ch=getchar();
        }
        return data;
    }
    bool cmp(query x,query y)
    {
        if (blo[x.l]==blo[y.l]) return x.r<y.r;
        return blo[x.l]<blo[y.l];
    }
    void build()
    {
        ret=1;
        for (int i=1;i<=n;i++)
        {
            blo[i]=ret;
            if (!(i%len)) {st[ret]=i;if (i!=n) ret++;}
        }
        if (n%len) st[ret]=n;
    }
    void modify(int x,int y)
    {
        bool flag=cnt[x];
        cnt[x]+=y;
        if ((!cnt[x]) && (flag)) val[blo[x]]--;
        if ((cnt[x]) && (!flag)) val[blo[x]]++;
    }
    int ask(int l,int r)
    {
        int ret1=0,ret2=0;
        for (int i=1;i<=blo[l-1]-1;i++) ret1+=val[i];
        for (int i=st[blo[l-1]-1]+1;i<=l-1;i++) ret1+=(cnt[i]>0);
        for (int i=1;i<=blo[r]-1;i++) ret2+=val[i];
        for (int i=st[blo[r]-1]+1;i<=r;i++) ret2+=(cnt[i]>0);
        return ret2-ret1;
    }
    int main()
    {
        n=read();m=read();
        for (int i=1;i<=n;i++) a[i]=read();
        for (int i=1;i<=m;i++)
        {
            scanf("%d%d%d%d",&a1,&a2,&a3,&a4);
            q[i]=query(a1,a2,a3,a4,i);
        }
        build();
        sort(q+1,q+m+1,cmp);
        for (int i=1;i<=m;i++)
        {
            for (;p1>q[i].l;p1--) modify(a[p1-1],1);
            for (;p1<q[i].l;p1++) modify(a[p1],-1);
            for (;p2>q[i].r;p2--) modify(a[p2],-1);
            for (;p2<q[i].r;p2++) modify(a[p2+1],1);
            ans[q[i].id]=ask(q[i].a,q[i].b);
        }
        for (int i=1;i<=m;i++) printf("%d
    ",ans[i]);
        return 0;
    }
  • 相关阅读:
    邂逅明下(巴什博弈+hdu2897)
    抽象接口的过程小结
    线程经常使用操作
    对继承的再次理解
    阿里Java开发手冊之编程规约
    [持续更新]Windows Programming常见Hungarian Notation/Abbreviation大全
    [转]__cdecl与__stdcall
    private继承的作用
    [转]C++中的三种继承public,protected,private
    如何只利用NMAKE+CL+LINK写WIN32程序
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/6434375.html
Copyright © 2020-2023  润新知