1. 程式人生 > >P1494 [國家集訓隊]小Z的襪子(莫隊演算法)

P1494 [國家集訓隊]小Z的襪子(莫隊演算法)

莫隊板子

程式碼

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define int long long
using namespace std;
struct Query{
    int l,r,aid;
}query[55000];
int ansa[55000],ansb[55000],c[55000],blocknum,midans,sz,belong[55000],n,m,a[55000],lx,rx;
bool cmp(Query a,Query b){
    return belong[a.l]==belong[b.l]?a.r<b.r:a.l<b.l;
}
int gcd(int a,int b){
    return (b==0)?a:gcd(b,a%b);
}
void move(int pos,int cs){
    midans-=c[a[pos]]*(c[a[pos]]);
    c[a[pos]]+=cs;
    midans+=c[a[pos]]*(c[a[pos]]);
}
signed main(){
    scanf("%lld %lld",&n,&m);
    sz=sqrt(n);
    blocknum=n/sz;
    if(n%sz)
        blocknum++;
    for(int i=1;i<=n;i++){
        scanf("%lld",&a[i]);
        belong[i]=(i-1)/sz+1;
    }
    for(int i=1;i<=m;i++)
        scanf("%lld %lld",&query[i].l,&query[i].r),query[i].aid=i;
    sort(query+1,query+m+1,cmp);
    lx=1,rx=0;
    for(int i=1;i<=m;i++){
        while(lx<query[i].l)
            move(lx,-1),lx++;
        while(lx>query[i].l)
            move(lx-1,1),lx--;
        while(rx<query[i].r)
            move(rx+1,1),rx++;
        while(rx>query[i].r)
            move(rx,-1),rx--;
        //move
        if(query[i].l==query[i].r){
            ansa[query[i].aid]=0,ansb[query[i].aid]=1;
            continue;
        }    
        ansa[query[i].aid]=midans-(query[i].r-query[i].l+1);
        ansb[query[i].aid]=(query[i].r-query[i].l+1)*(query[i].r-query[i].l);
        int Gcd=gcd(ansa[query[i].aid],ansb[query[i].aid]);
        ansa[query[i].aid]/=Gcd;
        ansb[query[i].aid]/=Gcd;
    }
    for(int i=1;i<=m;i++)
        printf("%lld/%lld\n",ansa[i],ansb[i]);
    return 0;
}