zoukankan      html  css  js  c++  java
  • 莫队+带修莫队模板与总结

    以下总结参考了许多大佬们的博客,开篇先(大佬)%

    莫队的入门题目主要为莫队和带修莫队在,这里就先在这里总结一下这两类题目的一些属性。

    我认为莫队本质是一种比较优化的暴力查找法。在通过分块操作后把复杂度降低。这个降低的复杂度的大小主要和你分块的方法有着巨大的关系。

    普通的莫队,n个元素m个区间询问,他的最佳分块大小为  n/√m   ,如果默认n==m的话  复杂度会降到 O(n*√n)  即可以完美运行5X10e5数据。

    带修的莫队,多加了一个让指针移动的因子—时间 t  ,时间复杂度比较难求,如果设定n,m,t相等的情况下 复杂度O(nlogn+n5/3),同样可以运行50000数据。

    贴两道经典的莫队存板子。

    P1494 [国家集训队]小Z的袜子 https://www.luogu.org/problemnew/show/P1494

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    ll b,ans=0;int l=1,r=0;
    ll gcd(ll a,ll b)
    {
        if(b==0) return a;
        else return gcd(b,a%b);
    }
    struct dd
    {
        int x,y,num;
    }a[50050];
    ll cmp(dd x,dd y)
    {
        if(x.x/b==y.x/b) return x.y<y.y;
        else return x.x<y.x;
    }
    ll bj[50050]={0};
    ll c[50050];
    pair<int,int> pr[50050];
    void solve(int x,int add)
    {
        ans-=bj[c[x]]*bj[c[x]];
        //cout<<ans<<endl;
        bj[c[x]]+=add;
        ans+=bj[c[x]]*bj[c[x]];
        //cout<<ans<<endl;
    }
    int main()
    {
        ll n,m,q,i,j;
        scanf("%lld%lld",&n,&q);
        b=sqrt(n);
        for(i=1;i<=n;i++) scanf("%lld",&c[i]);
        for(i=1;i<=q;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].num=i;
        sort(a+1,a+q+1,cmp);
         
        for(i=1;i<=q;i++)
        {
            ll lon=a[i].y-a[i].x+1;
            //cout<<a[i].x<<" "<<a[i].y<<"lon="<<lon<<endl;
            while(l<a[i].x)
            {
                solve(l,-1);l++;
            }
            while(l>a[i].x)
            {
                solve(l-1,1);l--;
            }
            while(r<a[i].y)
            {
                solve(r+1,1);r++;
            }
            while(r>a[i].y)
            {
                solve(r,-1);r--;
            }
            //cout<<l<<" "<<r<<endl;
            int aans=ans-lon;
            lon=lon*(lon-1);
            int gc=gcd(aans,lon);
            //cout<<ans<<" "<<lon<<endl;
            if(aans==0) pr[a[i].num].first=0,pr[a[i].num].second=1;
            else pr[a[i].num].first=aans/gc,pr[a[i].num].second=lon/gc;
        }
        for(i=1;i<=q;i++) printf("%d/%d
    ",pr[i].first,pr[i].second);
    }

    P1903 [国家集训队]数颜色 / 维护队列 https://www.luogu.org/problemnew/show/P1903

    #include<bits/stdc++.h>
    using namespace std;
    int ans=0;int l=1,r=0,t=0;
    int b;
    struct dd
    {
        int x,y,t,num;
    }a[50050];
    struct dt
    {
        int p, v;
    }tw[50050];
    int cmp(dd x,dd y)
    {
        if(x.x/b==y.x/b)
        {
            if(x.y/b==y.y/b) return x.t<y.t;
            return x.y/b<y.y/b;
         } 
        else return x.x<y.x;
    }
    int bj[1000050]={0};
    int e=0,tim=0;
    int c[50050];
    int pr[50050];
    void solve(int x,int add)
    {
        bj[c[x]]+=add;
        if(bj[c[x]]==0&&add==-1) ans--;
        if(bj[c[x]]==1&&add==1) ans++;
        //cout<<ans<<endl;
    }
    void time_change(int i,int tt)
    {
        if(tw[tt].p>=a[i].x&&tw[tt].p<=a[i].y) 
        {
            bj[c[tw[tt].p]]--;
            if(bj[c[tw[tt].p]]==0) ans--;
            bj[tw[tt].v]++;
            if(bj[tw[tt].v]==1) ans++;
        }
        swap(tw[tt].v,c[tw[tt].p]);
    }
    int main()
    {
        int n,q,i;
        char qq[5];
        scanf("%d%d",&n,&q);
        b=pow(n,0.66666);
        for(i=1;i<=n;i++) scanf("%d",&c[i]);
        for(i=1;i<=q;i++) 
        {
            scanf("%s",qq);
            if(qq[0]=='Q')
            {
                e++;
                scanf("%d%d",&a[e].x,&a[e].y);
                a[e].t=tim;
                a[e].num=e;
            }
            else
            {
                tim++;
                scanf("%d%d",&tw[tim].p,&tw[tim].v);
            }
        }
        sort(a+1,a+e+1,cmp);
        
        for(i=1;i<=e;i++)
        {
            //cout<<a[i].x<<" "<<a[i].y<<"lon="<<lon<<endl;
            while(l<a[i].x)
            {
                solve(l,-1);l++;
            }
            while(l>a[i].x)
            {
                solve(l-1,1);l--;
            }
            while(r<a[i].y)
            {
                solve(r+1,1);r++;
            }
            while(r>a[i].y)
            {
                solve(r,-1);r--;
            }
            //cout<<l<<" "<<r<<endl;
            while(t<a[i].t)
            {
                time_change(i,t+1);
                t++;
            }
            while(t>a[i].t)
            {
                time_change(i,t);
                t--;
            }
            //cout<<ans<<" "<<lon<<endl;
            pr[a[i].num]=ans;
        }
        for(i=1;i<=e;i++) printf("%d
    ",pr[i]);
    }
  • 相关阅读:
    LeetCode(111) Minimum Depth of Binary Tree
    LeetCode(108) Convert Sorted Array to Binary Search Tree
    LeetCode(106) Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode(105) Construct Binary Tree from Preorder and Inorder Traversal
    LeetCode(99) Recover Binary Search Tree
    【Android】通过经纬度查询城市信息
    【Android】自定义View
    【OpenStack Cinder】Cinder安装时遇到的一些坑
    【积淀】半夜突然有点想法
    【Android】 HttpClient 发送REST请求
  • 原文地址:https://www.cnblogs.com/wsblm/p/10813007.html
Copyright © 2011-2022 走看看