BZOJ 2038: [2009国家集训队]小Z的袜子(hose) 【莫队算法模版】
任意门:https://www.lydsy.com/JudgeOnline/problem.php?id=2038
题意概括:
有 N 只袜子(分别编号为1~N),有 M 次查询 (L, R)里面随机拿两只袜子,拿到相同颜色袜子的概率是多少。
解题思路:
莫队算法经典题,暴力找出区间内相同颜色的袜子的个数,排列组合最后得出结果。
入门题,当模版。
AC code:
1 #include <cstdio> 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 #define LL long long 6 using namespace std; 7 8 const int MAXN = 5e4+10; 9 int pos[MAXN], c[MAXN]; 10 LL s[MAXN], res; 11 int N, M, L = 1, R = 0; 12 13 LL gcd(LL a, LL b){return b==0?a:gcd(b, a%b);} 14 LL sqr(LL x){return x*x;} 15 struct date{ 16 int l, r, id; 17 LL so, mo; 18 }q[MAXN]; 19 bool cmp(date a, date b){ 20 if(pos[a.l]==pos[b.l]) return a.r < b.r; 21 return a.l < b.l; 22 } 23 bool CMP(date a, date b){ 24 return a.id < b.id; 25 } 26 void Update(int x, int add) 27 { 28 //res-=sqr(s[c[x]]); 29 res-=s[c[x]]*s[c[x]]; 30 s[c[x]]+=add; 31 res+=s[c[x]]*s[c[x]]; 32 //res+=sqr(s[c[x]]); 33 } 34 35 int main() 36 { 37 scanf("%d%d", &N, &M); 38 int sz = sqrt(N); 39 for(int i = 1; i <= N; i++){ 40 scanf("%d", &c[i]); 41 //pos[i] = (i-1)/sz+1; 42 pos[i] = i/sz; 43 } 44 for(int i = 1; i <= M; i++){ 45 scanf("%d%d", &q[i].l, &q[i].r); 46 q[i].id = i; 47 } 48 sort(q+1, q+M+1, cmp); 49 for(int i = 1; i <= M; i++){ 50 while(R < q[i].r){R++; Update(R, 1);} 51 while(R > q[i].r){Update(R, -1); R--;} 52 while(L < q[i].l){Update(L, -1); L++;} 53 while(L > q[i].l){L--; Update(L, 1);} 54 if(q[i].l == q[i].r){ 55 q[i].so = 0;q[i].mo = 1; 56 continue; 57 } 58 q[i].so = res-(q[i].r-q[i].l+1); 59 q[i].mo = (LL)(q[i].r-q[i].l+1)*(q[i].r-q[i].l); 60 LL k = gcd(q[i].so, q[i].mo); 61 q[i].so/=k;q[i].mo/=k; 62 } 63 sort(q+1, q+M+1, CMP); 64 for(int i = 1; i <= M; i++){ 65 printf("%lld/%lld\n", q[i].so, q[i].mo); 66 } 67 return 0; 68 }