BZOJ 2038 小Z的袜子

来源:互联网 发布:软件授权许可协议 编辑:程序博客网 时间:2024/05/01 07:38

【题意】中问题面。

【解题思路】对于L,R的询问。设其中颜色为x,y,z....的袜子的个数为a,b,c。。。那么答案即为(a*(a-1)/2+b*(b-1)/2+c*(c-1)/2....)/((R-L+1)*(R-L)/2)化简得:(a^2+b^2+c^2+...x^2-(a+b+c+d+.....))/((R-L+1)*(R-L))即:(a^2+b^2+c^2+...x^2-(R-L+1))/((R-L+1)*(R-L))所以这道题目的关键是求一个区间内每种颜色数目的平方和。但问题时怎么快速求解呢?

莫队算法。

【AC 代码】开始莫队的排序写错了,WA了几发。

//BZOJ 2038//Mo queue.#include <cmath>#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>using namespace std;#define ll long longconst int maxn=50010;int col[maxn];ll num[maxn],p[maxn],up[maxn],dw[maxn],aa,bb,cc;ll ans;int n,m;int pos[maxn];struct Q{    int l,r,id;}q[maxn];bool cmp(Q a,Q b){    if(pos[a.l]==pos[b.l]) return a.r<b.r;    return pos[a.l]<pos[b.l];}bool cmp2(Q a,Q b){    return a.id<b.id;}void update(int x,int d){    ans-=num[col[x]]*num[col[x]];    num[col[x]]+=d;    ans+=num[col[x]]*num[col[x]];}void solve(){    for(int i=0,l=1,r=0;i<m;i++){for(;r<q[i].r;r++)update(r+1,1);for(;r>q[i].r;r--)    update(r,-1);for(;l<q[i].l;l++)    update(l,-1);for(;l>q[i].l;l--)    update(l-1,1);if(q[i].l==q[i].r){up[q[i].id]=0;dw[q[i].id]=0;continue;}up[q[i].id]=ans-(q[i].r-q[i].l+1);dw[q[i].id]=(ll)(q[i].r-q[i].l+1)*(q[i].r-q[i].l);ll k=__gcd(up[q[i].id],dw[q[i].id]);up[q[i].id]/=k;dw[q[i].id]/=k;}}int main(){    while(scanf("%d%d",&n,&m)!=EOF)    {        memset(num,0,sizeof(num));        int sz=ceil(1.0*sqrt(n));        for(int i=1; i<=n; i++){            scanf("%d",&col[i]);            pos[i]=(i-1)/sz;        }        for(int i=0; i<m; i++){            scanf("%d%d",&q[i].l,&q[i].r);            q[i].id=i;        }        sort(q,q+m,cmp);        ans=0;        solve();        for(int i=0; i<m; i++){            printf("%lld/%lld\n",up[i],dw[i]);        }    }    return 0;}


0 0
原创粉丝点击