[BZOJ 2038]小Z的袜子

danihao123 posted @ 2017年1月27日 13:59 in 题解 with tags BZOJ 离线处理 莫队算法 , 652 阅读
转载请注明出处:http://danihao123.is-programmer.com/

今年第一更……噫

终于学会莫队了,不过目前只能做这样的模板题……

代码:

#include <cstdio>
#include <cmath>
#include <algorithm>
#include <utility>
using namespace std;
const int maxn=50005;
typedef long long ll;
ll gcd(ll a,ll b){
    if(!b){
        return a;
    }else{
        return gcd(b,a%b);
    }
}
ll C2(ll n){
    register ll temp,ns1=n-1;
    if(n&1){
        temp=ns1>>1;
        return temp*n;
    }else{
        temp=n>>1;
        return temp*ns1;
    }
}
 
struct Node{
    int L_s;
    int L,R;
    int id;
    ll ans1,ans2;
};
bool cmp1(const Node& a,const Node& b){
    if(a.L_s==b.L_s){
        return a.R<b.R;
    }else{
        return a.L_s<b.L_s;
    }
}
bool cmp2(const Node& a,const Node& b){
    return a.id<b.id;
}
Node Q[maxn];
int C[maxn],d[maxn];
int n,m;
inline void add_p(int x,ll &ans){
    d[x]++;
    ans+=d[x]-1;
}
inline void sub_p(int x,ll &ans){
    d[x]--;
    ans-=d[x];
}
inline void Mo(){
    register int i,j,L_p,R_p,sqrt_n=sqrt(n+0.5);
    register ll ans,t_gcd,t2;
    for(i=1;i<=m;i++){
        Q[i].L_s=Q[i].L/sqrt_n;
    }
    sort(Q+1,Q+1+m,cmp1);
    L_p=R_p=Q[1].L;
    ans=0;
    d[C[L_p]]++;
    for(i=1;i<=m;i++){
        while(L_p<Q[i].L){
            sub_p(C[L_p],ans);
            L_p++;
        }
        while(L_p>Q[i].L){
            L_p--;
            add_p(C[L_p],ans);
        }
        while(R_p<Q[i].R){
            R_p++;
            add_p(C[R_p],ans);
        }
        while(R_p>Q[i].R){
            sub_p(C[R_p],ans);
            R_p--;
        }
        t2=C2(R_p-L_p+1);
        t_gcd=gcd(ans,t2);
        Q[i].ans1=ans/t_gcd;
        Q[i].ans2=t2/t_gcd;
    }
    sort(Q+1,Q+1+m,cmp2);
}
 
int main(){
    register int i;
    int a,b;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++){
        scanf("%d",&C[i]);
    }
    for(i=1;i<=m;i++){
        Q[i].id=i;
        scanf("%d%d",&a,&b);
        Q[i].L=a;
        Q[i].R=b;
    }
    Mo();
    for(i=1;i<=m;i++){
        printf("%lld/%lld\n",Q[i].ans1,Q[i].ans2);
    }
    return 0;
}

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter