HYSBZ - 2038
传说中的莫队算法 时间 n*sqrt(n);
没的修改 然后从前往后跑 重复的就节约下来了
#include<stdio.h> #include<algorithm> #include<cstring> #include<string> #include<cmath> using namespace std; #define LL long long #define MAXN 50010 #define inf 1000000000.0 struct node { int l,r,id; }q[MAXN]; int pos[MAXN]; int cnt[MAXN]; int num[MAXN]; LL ansl[MAXN],ansr[MAXN]; bool cmp(node a,node b) { if(pos[a.l]==pos[b.l]) return a.r<b.r; return pos[a.l]<pos[b.l]; } LL gcd(LL a,LL b) { return b?gcd(b,a%b):a; } int main() { int n,m; while(scanf("%d%d",&n,&m)!=EOF) { for(int i=1;i<=n;i++) scanf("%d",&num[i]); for(int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; //第几个 } int sz=sqrt(n); for(int i=1;i<=n;i++) pos[i]=i/sz; //分块中第几个 sort(q+1,q+m+1,cmp); memset(cnt,0,sizeof(cnt)); int l,r; LL ans; l=r=1; ans=0; cnt[num[1]]++; //第一个放进去 for(int i=1;i<=m;i++) { if(r<q[i].r) { for(int k=r+1;k<=q[i].r;k++) { ans -= cnt[num[k]] *(cnt[num[k]]-1); cnt[num[k]]++; ans += cnt[num[k]] *(cnt[num[k]]-1); } } else if(r>q[i].r) { for(int k=r;k>q[i].r;k--) { ans -= cnt[num[k]]*(cnt[num[k]]-1); cnt[num[k]]--; ans += cnt[num[k]]*(cnt[num[k]]-1); } } if(l<q[i].l) { for(int k=l;k<q[i].l;k++) { ans -= cnt[num[k]]*(cnt[num[k]]-1); cnt[num[k]]--; ans += cnt[num[k]]*(cnt[num[k]]-1); } } else if(l>q[i].l) { for(int k=l-1;k>=q[i].l;k--) { ans -= cnt[num[k]] *(cnt[num[k]]-1); cnt[num[k]]++; ans += cnt[num[k]] *(cnt[num[k]]-1); } } l = q[i].l; r = q[i].r; LL len = q[i].r-q[i].l+1; LL tot = len*(len -1); LL d = gcd(ans,tot); ansl[q[i].id]=ans/d; ansr[q[i].id]=tot/d; } for(int i=1;i<=m;i++) printf("%lld/%lld\n",ansl[i],ansr[i]); } return 0; }
posted on 2017-03-07 19:22 HelloWorld!--By-MJY 阅读(182) 评论(0) 编辑 收藏 举报