题意:中文题。。。
用分块写的,每次增加一个数x,能形成的种数,ans就增加2*cnt[x],然后再cnt[x]++,每减少一个数,cnt[x]--,ans减少2*cnt[x]。。。就是这样搞了。。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
const int MAXN=50010;
int vec[MAXN],idx;
int a[MAXN];
int cnt[MAXN];
typedef long long ll;
ll ans1[MAXN],len[MAXN];
struct Query
{
int l,r,pos,id;
bool operator < (const Query &rhs) const
{
if(pos==rhs.pos)
return r<rhs.r;
return pos<rhs.pos;
}
}q[MAXN];
int HASH(int x)
{
int l=1,r=idx;
while(l<=r)
{
int mid=(l+r)>>1;
if(vec[mid]==x)
return mid;
if(x>vec[mid])
l=mid+1;
else
r=mid-1;
}
return l;
}
ll ans;
void erase(int x)
{
cnt[a[x]]--;
ans-=2*cnt[a[x]];
}
void insert(int x)
{
ans+=2*cnt[a[x]];
cnt[a[x]]++;
}
ll gcd(ll a,ll b)
{
return b==0?a:gcd(b,a%b);
}
int main()
{
int n,m,i;
while(scanf("%d%d",&n,&m)==2)
{
idx=0;
for(i=1;i<=n;i++)
{
scanf("%d",&a[i]);
vec[++idx]=a[i];
}
vec[1]=a[1];
sort(vec+1,vec+idx+1);
int k=1;
for(i=2;i<=idx;i++)
{
if(vec[k]!=vec[i])
vec[++k]=vec[i];
}
for(i=1;i<=n;i++)
{
a[i]=HASH(a[i]);
}
for(i=0;i<m;i++)
{
scanf("%d%d",&q[i].l,&q[i].r);
q[i].pos=q[i].l/sqrt(n);
q[i].id=i;
}
sort(q,q+m);
int p1=1,q1=1;
cnt[a[p1]]++;
ans=0;
for(i=0;i<m;i++)
{
int l=q[i].l,r=q[i].r;
while(q1<r)
insert(++q1);
while(q1>r)
erase(q1--);
while(p1<l)
erase(p1++);
while(p1>l)
insert(--p1);
ans1[q[i].id]=ans;
len[q[i].id]=(ll)(q[i].r-q[i].l+1)*(ll)(q[i].r-q[i].l);
}
for(i=0;i<m;i++)
{
ll temp1=ans1[i];
ll temp2=len[i];
if(temp1==0)
{
printf("0/1\n");
continue;
}
ll d=gcd(temp1,temp2);
temp1/=d,temp2/=d;
printf("%lld/%lld\n",temp1,temp2);
}
}
return 0;
}