题目:点击此处
思路:求出每个区间中从每种颜色中选两个 的种类数的和
如果和为零输出0/1
否则输出 和/ ( (r-l+1)*(r-l)/2 ) 最简形式
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <queue>
#include <algorithm>
#define ll long long
using namespace std;
const int maxn=1e6+5;
struct node
{
ll l,r,i;
}pos[maxn];
ll n,block,q,l,r,ans=0;
ll mp[maxn],c[maxn],a[maxn];
struct an{
ll zi,mu;
}answer[maxn];
bool cmp(node a,node b)
{
if(a.l/block!=b.l/block)
return a.l/block<b.l/block;
return a.r<b.r;
}
void add(ll x)
{
ans+=mp[a[x]];
mp[a[x]]++;
}
void remov1e(ll x)
{
mp[a[x]]--;
ans-=mp[a[x]];
}
int main()
{
scanf("%lld%lld",&n,&q);block=sqrt(1.0*n);
for(ll i=1;i<=n;i++)
scanf("%lld",&a[i]);
for(ll i=1;i<=q;i++)
{
scanf("%lld%lld",&pos[i].l,&pos[i].r);
pos[i].i=i;
}
sort(pos+1,pos+1+q,cmp);
ll cl=pos[1].l,cr=cl-1;
for(ll i=1;i<=q;i++)
{
l=pos[i].l,r=pos[i].r;
while(cl<l)
{
remov1e(cl);
cl++;
}
while(cl>l)
{
add(cl-1);
cl--;
}
while(cr<r)
{
add(cr+1);
cr++;
}
while(cr>r)
{
remov1e(cr);
cr--;
}
ll zi=ans;
if(zi==0)
{
answer[pos[i].i].zi=0;
answer[pos[i].i].mu=1;
}
else {
ll mu=(r-l+1)*(r-l)/2;
ll g=__gcd(zi,mu);
zi/=g;mu/=g;
answer[pos[i].i].zi=zi;
answer[pos[i].i].mu=mu;
}
}
for(ll i=1;i<=q;i++)
cout<<answer[i].zi<<"/"<<answer[i].mu<<endl;
return 0;
}