题目大意:有n个袜子,m个询问,每个询问给一个区间[L,R],问他有多大的概率抽到两只颜色相同的袜子
题解:离线,按l所在块为第一关键字,r为第二关键字排序,然后莫队
C++ Code:
#include<cstdio> #include<algorithm> using namespace std; struct node{ long long l,r,num; }q[50100]; inline bool cmp(node a,node b){ if (a.l/224==b.l/224)return a.r<b.r; return a.l<b.l; } long long gcd(long long a, long long b){ if (b==0)return a; return gcd(b,a%b); } long long n,m,num[50100],cnt[50100],ans[50100][2]; int main() { scanf("%lld%lld",&n,&m); for (long long i=1;i<=n;i++)scanf("%lld",&num[i]); for (long long i=0;i<m;i++)scanf("%lld%lld",&q[i].l,&q[i].r),q[i].num=i+1; sort(q,q+m,cmp); long long l=1,r=1,now=0; cnt[num[1]]=1; for (long long i=0;i<m;i++) { while (r>q[i].r)now-=--cnt[num[r--]]; while (r<q[i].r)now+=cnt[num[++r]]++; while (l<q[i].l)now-=--cnt[num[l++]]; while (l>q[i].l)now+=cnt[num[--l]]++; ans[q[i].num][0]=now;ans[q[i].num][1]=q[i].r-q[i].l+1; } for (long long i=1;i<=m;i++) { long long tmp=ans[i][1]*(ans[i][1]-1)>>1,e=gcd(ans[i][0],tmp); if (!e)puts("0/1"); else printf("%lld/%lld\n",ans[i][0]/e,tmp/e); } return 0; }