• P1494 [国家集训队]小Z的袜子


    传送门

    经典的莫队

    考虑一种颜色对答案的贡献 : 

    设此颜色的数量为 cnt,那么有 cnt * ( cnt - 1 ) 种方案拿到两只此颜色袜子

    设总数为 sum,那么一共有 sum * ( sum-1 ) 种不同的拿袜子方案

    只要把所有同色的方案除以总方案就是我们的答案了

    那么我们可以同时维护拿到同色的方案总数 x 和总方案数 y

    设 cnt [ x ] 表示当前颜色为 x 的袜子的总数

    对于一个新加入的袜子,此颜色的袜子的数量 + 1

    那么原本为 cnt * ( cnt - 1 ) 的方案数变成了 ( cnt + 1 ) * cnt

    相当于多了 2 * cnt (注意此时 cnt 是此袜子加入前的数量)

    注意总方案数也有增加,从 sum * ( sum - 1 ) 到 ( sum + 1 ) * sum

    所以要考虑对 x 和 y 的贡献

    如果减少也是相同的道理,很容易推出来的

    最后一定要注意 x 和 y 要开long long !

    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #include<cmath>
    #include<cstring>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=5e4+7;
    int n,m,col[N];
    struct data
    {
        int l,r,id,pos;
        inline bool operator < (const data &tmp) const {
            return pos!=tmp.pos ? pos<tmp.pos : r<tmp.r;
        }
    }d[N];//存询问
    
    int cnt[N];
    ll ans[N][2],x,y;
    ll gcd(ll a,ll b) { return b ? gcd(b,a%b) : a; }//用来约分
    int main()
    {
        n=read(); m=read();
        for(int i=1;i<=n;i++) col[i]=read();
        int t=sqrt(n)+1;
        for(int i=1;i<=m;i++)
        {
            d[i].l=read(); d[i].r=read();
            d[i].id=i; d[i].pos=(d[i].l-1)/t+1;
        }
        sort(d+1,d+m+1);
        int l=1,r=0;
        for(int i=1;i<=m;i++)
        {
            while(r<d[i].r) r++,x+=2*cnt[col[r]],y+=2*(r-l),cnt[col[r]]++;
            while(r>d[i].r) x-=2*cnt[col[r]]-2,y-=2*(r-l+1)-2,cnt[col[r]]--,r--;
            while(l<d[i].l) x-=2*cnt[col[l]]-2,y-=2*(r-l+1)-2,cnt[col[l]]--,l++;
            while(l>d[i].l) l--,x+=2*cnt[col[l]],y+=2*(r-l),cnt[col[l]]++;
            //注意细节
            if(x)//注意特判
            {
                ll g=gcd(x,y);
                ans[d[i].id][0]=x/g; ans[d[i].id][1]=y/g;
            }
            else ans[d[i].id][0]=0,ans[d[i].id][1]=1;
        }
        for(int i=1;i<=m;i++) printf("%lld/%lld
    ",ans[i][0],ans[i][1]);
        return 0;
    }
  • 相关阅读:
    Struts2(十六)Json
    Struts2(十五)实现文件上传
    Struts2(十四)拦截器实现权限管理
    Eclipse下link方式安装插件
    Struts2(十三)国际化-internationalization
    Struts2(十二)使用验证框架验证数据较验
    Struts2(十一)OGNL标签三与Struts2标签
    Struts2(十)OGNL标签二与Struts2标签
    Struts2(九)OGNL标签一与Struts2标签
    Elasticsearch 分词器
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/9828271.html
Copyright © 2020-2023  润新知