zoukankan      html  css  js  c++  java
  • 莫队

    莫队就是离线处理一些问题。

    当一个问题[l,r]可以由[l-1,r],[l,r+1],[l+1,r],[l,r-1]相差一的区间由O(1)或O(logn)推出时,就可以用莫队莫队实质上是离线处理,通过改变询问的顺序使复杂度降到O(n^1.5)

    其实莫队用到分块的地方仅仅是排序中用到?

    排序的过程:先计算每个位置应该处于哪个块中,记为pos[i],按(pos[i],r)双关键字排序,然后再对每个区间暴力计算

    bzoj2038&&bzoj3781

    题解太多了

    大概就是个裸的莫队

    bzoj2038

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    struct data
    {
        ll a,b;
        int l,r,id;
    }a[100010];
    int n,m;
    ll tot;
    int c[100010];
    ll cnt[100010],pos[100010];
    ll gcd(ll a,ll b)
    {
        return b==0?a:gcd(b,a%b);
    }
    bool cp1(data x,data y)
    {
        if(pos[x.l]!=pos[y.l]) return pos[x.l]<pos[y.l];
        return x.r<y.r;
    }
    bool cp2(data x,data y)
    {
        return x.id<y.id;
    }
    void update(int x,int delta)
    {
        tot-=cnt[c[x]]*(cnt[c[x]]-1)/2;
        cnt[c[x]]+=delta;
        tot+=cnt[c[x]]*(cnt[c[x]]-1)/2;
    }
    void solve()
    {
        for(int i=1,l=1,r=0;i<=m;i++)
        {
    //        printf("a[i].l=%d a[i].r=%d
    ",a[i].l,a[i].r);
            while(r<a[i].r) {
                r++; update(r,1);
            }
            while(r>a[i].r) {
                update(r,-1); r--; 
            }
            while(l<a[i].l) {
                update(l,-1); l++; 
            }
            while(l>a[i].l) {
                l--; update(l,1);
            }
            if(a[i].l==a[i].r)
            {
                a[i].a=0; a[i].b=1;
                continue;
            }
    //        for(int j=1;j<=n;j++)
    //        {
    //            printf("color[%d]=%d
    ",c[j],cnt[c[j]]);
    //        }
    //        printf("l=%d r=%d
    ",l,r);
    //        printf("tot=%d
    ",tot);
            a[i].a=tot; a[i].b=(ll)(a[i].r-a[i].l+1)*(ll)(a[i].r-a[i].l)/2;
            ll k=gcd(a[i].b,a[i].a);
            a[i].a/=k;
            a[i].b/=k;
            if(a[i].a==0) a[i].b=1;
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
        } 
        int size=(int)(sqrt(n));
        for(int i=1;i<=n;i++)
        {
            pos[i]=(i-1)/size+1;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].id=i;
        }
        sort(a+1,a+m+1,cp1);
        solve();
        sort(a+1,a+m+1,cp2);
        for(int i=1;i<=m;i++)
        {
            printf("%lld/%lld
    ",a[i].a,a[i].b);
        }
        return 0;
    }

    bzoj3781

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    using namespace std;
    #define N 500010
    struct data 
    {
        int l,r,pos,ans;
    }a[N];
    int n,m,k,ans;
    int cnt[N],c[N],pos[N];
    bool cp(data x,data y)
    {
        if(pos[x.l]!=pos[y.l]) return pos[x.l]<pos[y.l];
        return x.r<y.r;
    }
    bool cp1(data x,data y)
    {
        return x.pos<y.pos;
    }
    void update(int pos,int delta)
    {
        ans-=cnt[c[pos]]*cnt[c[pos]];
        cnt[c[pos]]+=delta;
        ans+=cnt[c[pos]]*cnt[c[pos]];
    }
    void solve()
    {
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
    //        printf("a[i].l=%d a[i].r=%d
    ",a[i].l,a[i].r);
            while(l<a[i].l) {
                update(l,-1); l++; 
            }
            while(l>a[i].l) {
                l--; update(l,1); 
            }
            while(r>a[i].r) {
                update(r,-1); r--; 
            }
            while(r<a[i].r) {
                r++; update(r,1); 
            }
            a[i].ans=ans;
        }
    }
    int main()
    {
        scanf("%d%d%d",&n,&m,&k);
        int size=(int)(sqrt(n));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&c[i]);
            pos[i]=(i-1)/size+1;
        }
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d",&a[i].l,&a[i].r);
            a[i].pos=i;
        }
        sort(a+1,a+m+1,cp);
        solve();
        sort(a+1,a+m+1,cp1);
        for(int i=1;i<=m;i++)
        {
            printf("%d
    ",a[i].ans);
        }
        return 0;
    }
  • 相关阅读:
    sqlserver 数据查询效率优化
    上海亲戚朋友游套餐
    C# List集合去重操作注意点
    一个高级开发的基本工作职责和能力要求
    对于程序员的经验能力和薪资待遇基本概括
    一个项目团队的最低配置
    【算法学习笔记】51. 贪心法 区间排序问题 SJTU OJ 1360 偶像丁姐的烦恼
    【算法学习笔记】50.字符串处理 SJTU OJ 1361 丁姐的周末
    【算法学习笔记】49.暴力穷举 BFS 剪枝 SJTU OJ 1357 相邻方案
    【算法学习笔记】48.递归/显式栈 SJTU OJ 1358 分割树
  • 原文地址:https://www.cnblogs.com/19992147orz/p/6181092.html
Copyright © 2011-2022 走看看