BZOJ-2308 小z的袜子(莫队)
题意
$n$点$m$次询问区间内随机取两个数是相同数的概率
思路
莫队入门题,对询问按块排序后更新答案,复杂度$O(n\sqrt{n})$
代码
//#pragma comment(linker, "/STACK:1024000000,1024000000") #include <map> #include <set> #include <cmath> #include <queue> #include <stack> #include <cstdio> #include <vector> #include <cassert> #include <cstring> #include <iostream> #include <algorithm> #define IOS ios::sync_with_stdio(0),cin.tie(0); #define DBG(x) cerr << #x << " = " << x << endl; using namespace std; typedef long long LL; typedef long double LD; typedef unsigned long long ULL; const int inf = 0x3f3f3f3f; const int mod = 1000000007; const double eps = 1e-8; const double pi = acos(-1.0); void file(){ freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout); } const int maxn = 5e4+5; int n,m,sz; LL Ans,a[maxn],cnt[maxn]; struct node{ LL l,r,id; }Q[maxn],ans[maxn]; bool cmp(node a,node b){ if(a.l/sz != b.l/sz)return a.l < b.l; return a.r < b.r; } void add(int x){ Ans+=cnt[a[x]]; cnt[a[x]]++; } void del(int x){ cnt[a[x]]--; Ans-=cnt[a[x]]; } void Mo(){ sort(Q+1,Q+1+m,cmp); int L=1,R=1; cnt[a[1]]=1;//视题目而定 for(int i=1;i<=m;i++){ while(L < Q[i].l)del(L),L++; while(L > Q[i].l)L--,add(L); while(R < Q[i].r)R++,add(R); while(R > Q[i].r)del(R),R--; LL tmp=Q[i].r-Q[i].l+1; ans[Q[i].id].l=(tmp*(tmp-1))/2; ans[Q[i].id].r=Ans; } } namespace BakuretsuMahou{ void Explosion(){ scanf("%d%d",&n,&m); sz=sqrt(n); for(int i=1;i<=n;i++)scanf("%lld",&a[i]); for(int i=1;i<=m;i++)scanf("%lld%lld",&Q[i].l,&Q[i].r),Q[i].id=i; Mo(); for(int i=1;i<=m;i++){ if(ans[i].r == 0)puts("0/1"); else{ LL G=__gcd(ans[i].r,ans[i].l); printf("%lld/%lld\n",ans[i].r/G,ans[i].l/G); } } } } int main(){ //IOS //file(); BakuretsuMahou::Explosion(); return 0; }
考试周了,我为什么还是这么摸鱼,可恶。