[2009国家集训队]小Z的袜子(hose)(莫队算法)

来源:互联网 发布:java message类 编辑:程序博客网 时间:2024/06/12 01:48

裸的莫队算法题目。区间[l,r]一共有C2rl+1=(rl)(rl+1)2种选取袜子的方案,假设在区间[l,r]内颜色为x的袜子有k只,那么有C2k=k(k1)2种选取方案。

#include<cstdio>#include<algorithm>#include<cmath>#define MAXN 50010using namespace std;typedef long long LL;int a[MAXN],n,m,block;LL now,cnt[MAXN];struct fs{    LL fz,fm;}ans[MAXN];LL gcd(LL a,LL b){    return b==0?a:gcd(b,a%b);}struct Q{    int l,r,id;    bool operator <(const Q &b)const    {        if(l/block == b.l/block) return r < b.r;        return l < b.l;    }}que[MAXN];void add(int x){    now -= cnt[x]*(cnt[x]-1)/2;    cnt[x]++;    now += cnt[x]*(cnt[x]-1)/2;}void del(int x){    now -= cnt[x]*(cnt[x]-1)/2;    cnt[x]--;    now += cnt[x]*(cnt[x]-1)/2;}int main(){    scanf("%d%d",&n,&m);    block = sqrt(n);    for(int i = 1; i <= n; i++)        scanf("%d",&a[i]);    for(int i = 0; i < m; i++)    {        scanf("%d%d",&que[i].l,&que[i].r);        que[i].id = i;    }    sort(que,que+m);    int currentL = 1,currentR = 0;    for(int i = 0; i < m; i++)    {        while(que[i].l < currentL) add(a[--currentL]);        while(que[i].l > currentL) del(a[currentL++]);        while(que[i].r > currentR) add(a[++currentR]);        while(que[i].r < currentR) del(a[currentR--]);        if(que[i].l == que[i].r)        {            ans[que[i].id].fz = 0;            ans[que[i].id].fm = 1;            continue;        }        ans[que[i].id].fz = now;        ans[que[i].id].fm = 1LL*(que[i].r-que[i].l)*(que[i].r-que[i].l+1)/2;//分母应该是长整形,调了半天QAQ        LL d = gcd(now,ans[que[i].id].fm);        ans[que[i].id].fz /= d;        ans[que[i].id].fm /= d;    }    for(int i = 0; i < m; i++)        printf("%lld/%lld\n",ans[i].fz,ans[i].fm);}
0 0
原创粉丝点击