莫队算法。

 

 https://blog.csdn.net/qq_38891827/article/details/82190013 很多例题

https://blog.csdn.net/qq_41117236/article/details/81453534

 

https://www.lydsy.com/JudgeOnline/problem.php?id=2038

不带修改的莫队。数区间内有多少个相同的元素。分块大小为n的1/2次方。复杂度为O(n的3/2次方)

#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=50000+10;
int col[maxn],Be[maxn];
ll sum[maxn],ans;
struct Mo{
    int l,r,ID;
    ll A,B;
}f[maxn];
ll GCD(ll a,ll b){return b==0?a:GCD(b,a%b);}
bool cmp(Mo a,Mo b){return Be[a.l]==Be[b.l]?a.r<b.r:a.l<b.l;}
bool CMP(Mo a,Mo b){return a.ID<b.ID;}
void revise(int x,int add)
{
    ans-=sum[col[x]]*(sum[col[x]]-1);
    sum[col[x]]+=add;
    ans+=sum[col[x]]*(sum[col[x]]-1);
}
int main()
{
    int n,m; scanf("%d%d",&n,&m);
    int unit=sqrt(n);
    for(int i=1;i<=n;i++)
        scanf("%d",&col[i]),Be[i]=i/unit+1;
    for(int i=1;i<=m;i++)
        scanf("%d%d",&f[i].l,&f[i].r),f[i].ID=i;
    sort(f+1,f+m+1,cmp);
    int l=1,r=0;
    for(int i=1;i<=m;i++){
        while(l<f[i].l) revise(l,-1),l++;
        while(l>f[i].l) revise(l-1,1),l--;
        while(r<f[i].r) revise(r+1,1),r++;
        while(r>f[i].r) revise(r,-1),r--;
        if(f[i].l==f[i].r){
            f[i].A=0;
            f[i].B=1;
            continue;
        }
        f[i].A=ans;
        f[i].B=1LL*(f[i].r-f[i].l+1)*(f[i].r-f[i].l); //分母:len*(len-1)
        ll gcd=GCD(f[i].A,f[i].B);
        f[i].A/=gcd;
        f[i].B/=gcd;
    }
    sort(f+1,f+m+1,CMP);
    for(int i=1;i<=m;i++)
        printf("%lld/%lld\n",f[i].A,f[i].B);
    return 0;
}

 

 

https://www.lydsy.com/JudgeOnline/problem.php?id=2120

待修改的莫队,分块大小为n的2/3次方,时间复杂度为O(n的5/3次方)

#include <bits/stdc++.h>
using namespace std;
const int maxn=10000+10;
struct Query{
    int l,r,Tim,ID;
}q[maxn];
struct Change{
    int pos,New,Old;
}c[maxn];
int s[maxn],Be[maxn];
int now[maxn],ans[maxn];
int color[maxn*100];
int Ans,l=1,r;
bool cmp(Query a,Query b)
{
    return Be[a.l]==Be[b.l]?(Be[a.r]==Be[b.r]?a.Tim<b.Tim:a.r<b.r):a.l<b.l;
}
void revise(int x,int d)
{
    color[x]+=d;
    if(d>0) Ans+=color[x]==1;
    if(d<0) Ans-=color[x]==0;
}
void going(int x,int d)
{
    if(l<=x&&x<=r) revise(d,1),revise(s[x],-1);
    s[x]=d;
}
int main()
{
    int n,m; scanf("%d%d",&n,&m);
    int unit=pow(n,2.0/3); 
    for(int i=1;i<=n;i++){
        scanf("%d",&s[i]);
        now[i]=s[i];
        Be[i]=i/unit+1; //分块
    }
    int Time=0,t=0;
    while(m--){
        char sign; int x,y;
        scanf(" %c %d%d",&sign,&x,&y);
        if(sign=='Q') q[++t]=(Query){x,y,Time,t};
        else c[++Time]=(Change){x,y,now[x]},now[x]=y;
    }
    sort(q+1,q+t+1,cmp);
    int T=0;
    for(int i=1;i<=t;i++){
        while(T<q[i].Tim) going(c[T+1].pos,c[T+1].New),T++;
        while(T>q[i].Tim) going(c[T].pos,c[T].Old),T--;
        while(l<q[i].l) revise(s[l],-1),l++;
        while(l>q[i].l) revise(s[l-1],1),l--;
        while(r<q[i].r) revise(s[r+1],1),r++;
        while(r>q[i].r) revise(s[r],-1),r--;
        ans[q[i].ID]=Ans;
    }
    for(int i=1;i<=t;i++) 
        printf("%d\n",ans[i]);
    return 0;
}

 

posted @ 2019-07-31 21:36  downrainsun  阅读(175)  评论(0编辑  收藏  举报