小z的袜子 莫队算法(分块思想) O(N*sqrt(N))

来源:互联网 发布:狗狗 知乎 编辑:程序博客网 时间:2024/06/11 19:41
#include <cstring>#include <cstdio>#include <iostream>#include <algorithm>#include <vector>#include <map>#include <cmath>#include <queue>#include <string>#include <set>#include <stack>using namespace std;#define ll long long#define eps 1e-8#define pi acos(-1.0)#define inf 0x3f3f3f3f#define mod 1000000007#define sqr(x) ((x)*(x))#define lson (u<<1)#define rson (u<<1|1)#define maxn 100100#define maxm 200100//#pragma comment(linker,"/STACK:102400000,102400000")int n,m;int color[maxn],cnt[maxn];ll sz[maxn],ans[maxn];struct Q{    int l,r,block;    int id;    bool operator<(const Q& q) const    {        if(block!=q.block) return block < q.block;        return r < q.r;    }}q[maxn];ll gcd(ll a,ll b){    return b?gcd(b,a%b):a;}int main(){    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)        scanf("%d",color+i);    int B = sqrt(m+0.5);    for(int i=0;i<m;i++){        scanf("%d%d",&q[i].l,&q[i].r);        if(q[i].l>q[i].r) swap(q[i].l,q[i].r);        sz[i] = q[i].r-q[i].l+1;        q[i].block = q[i].l/B;        q[i].id = i;    }    sort(q,q+m);    int L = q[0].l,R = q[0].r;    for(int i=L;i<=R;i++)        ans[q[0].id] += cnt[color[i]]++;    for(int i=1;i<m;i++){ans[q[i].id] = ans[q[i-1].id];        for(int j=q[i].l;j<L;j++)            ans[q[i].id] += cnt[color[j]]++;        for(int j=R+1;j<=q[i].r;j++)            ans[q[i].id] += cnt[color[j]]++;        for(int j=L;j<q[i].l;j++)            ans[q[i].id] -= (--cnt[color[j]]);        for(int j=q[i].r+1;j<=R;j++)            ans[q[i].id] -= (--cnt[color[j]]);        L = q[i].l, R = q[i].r;    }    for(int i=0;i<m;i++)    {        ll all = sz[i]*(sz[i]-1)/2;        ll d = gcd(ans[i],all);        ans[i] /= d, all /= d;        printf("%lld/%lld\n",ans[i],all);    }    return 0;}

0 0