因为考试题太难了改不出,于是就弃疗搞莫队算法去了
参考:《莫涛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
}