bzoj 2038 分类: bzoj temp...

因为考试题太难了改不出,于是就弃疗搞莫队算法去了


造福社会:莫涛2010年集训队论文


hzwer的写法极其简略,长跪不起


具体实现:
1.分块 S=sqrt(n)+ 双关键字排序
2.如下

 

[来自莫涛论文]

#include
#include
#include
#include
#include
const int MAXN = 50005, MAXM = 50005;

int n , m , S;
int color[MAXN] = {0}, cnt[MAXN] = {0};
int  l , r ;long long now ;

struct ques{int l,r,si,Num;long long a,b;}q[MAXM] = {0};

bool cmp(const ques &a, const ques &b)
{return (a.si < b.si)||(a.si == b.si && a.r < b.r);}
bool ncmp(const ques &a, const ques &b)
{return a.Numif(!b)return a;else return gcd(b,a%b);}

long long pow2(int x){return (long long)x*x;}

void add(int t,int w)
{
    now -= pow2(cnt[color[t]]);
    cnt[color[t]]+=w;
    now += pow2(cnt[color[t]]);
}

int main()
{
#ifndef ONLINE_JUDGE    
    freopen("bzoj2038.in","r",stdin);
    freopen("bzoj2038.out","w",stdout);
#endif

     scanf("%d%d",&n,&m);

     S = sqrt((double)n);

     for(int i = 1; i <= n; i++)
        scanf("%d",&color[i]);

     for(int i = 1; i <= m ; i++)
     {
       scanf("%d%d",&q[i].l,&q[i].r);   
       q[i].Num = i;
       q[i].si = (q[i].l-1)/S + 1;
     }

     std::sort(q+1,q+m+1,cmp);

     cnt[color[1]] = 1, l = r = 1 , now = 1;
     for(int i = 1; i <= m; i++)
     {
        if(l<=q[i].l) while(l < q[i].l){add(l,-1);l++;}
        else          while(l > q[i].l){--l;add(l,1);}

        if(r<=q[i].r) while(r < q[i].r){++r;add(r,1);}
        else          while(r > q[i].r){add(r,-1);r--;}

        if(q[i].l == q[i].r){q[i].a = 0 ,q[i].b = 1;}
        else
        {
         q[i].a = now - (r-l+1);
         q[i].b = ((long long)r-l+1)*(r-l);

         long long tmp = gcd(q[i].a,q[i].b);
         q[i].a/= tmp , q[i].b/=tmp;
        }
     }

     std::sort(q+1,q+m+1,ncmp);

     for(int i = 1 ; i <= m ; i++)
        printf("%lld/%lld\n",q[i].a,q[i].b);

#ifndef ONLINE_JDUGE
     fclose(stdin);
     fclose(stdout);
#endif      
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

转载于:https://www.cnblogs.com/dashgua/p/4723073.html

你可能感兴趣的:(bzoj 2038 分类: bzoj temp...)