标签:
莫队算法。
先分块,然后去统计。
莫队算法可以解决一类不修改、离线查询问题。
构造曼哈顿最小生成树的做法还没有写。
写了个直接分段解决的办法。
把1~n分成sqrt(n)段。
unit = sqrt(n)
m个查询先按照第几个块排序,再按照 R排序。
然后直接求解。
#include<bits/stdc++.h> #define N 50010 #define LL long long using namespace std; struct node { int l,r,id; }; int n,m; int pos[N],c[N]; LL a[N],b[N],s[N]; node q[N]; void init() { memset(s,0,sizeof(s)); int unit=int(sqrt(n)); for (int i=1;i<=n;i++) if (i%unit==0) pos[i]=i/unit; else pos[i]=i/unit+1; } bool cmp(node a, node b) { if (pos[a.l]==pos[b.l]) return a.r<b.r; else return pos[a.l]<pos[b.l]; } LL gcd(LL a, LL b) { if (b==0) return a; return gcd(b,a%b); } int main() { while(scanf("%d%d",&n,&m)!=EOF) { init(); for (int i=1;i<=n;i++) scanf("%d",&c[i]); for (int i=1;i<=m;i++) { scanf("%d%d",&q[i].l,&q[i].r); q[i].id=i; } sort(q+1,q+m+1,cmp); int l=1,r=1; LL tmp=1; s[c[1]]=1; for (int i=1;i<=m;i++) { while(r<q[i].r) { r++; tmp=tmp-s[c[r]]*s[c[r]]; s[c[r]]++; tmp=tmp+s[c[r]]*s[c[r]]; } while(r>q[i].r) { tmp=tmp-s[c[r]]*s[c[r]]; s[c[r]]--; tmp=tmp+s[c[r]]*s[c[r]]; r--; } while(l<q[i].l) { tmp=tmp-s[c[l]]*s[c[l]]; s[c[l]]--; tmp=tmp+s[c[l]]*s[c[l]]; l++; } while(l>q[i].l) { l--; tmp=tmp-s[c[l]]*s[c[l]]; s[c[l]]++; tmp=tmp+s[c[l]]*s[c[l]]; } a[q[i].id]=tmp-(q[i].r-q[i].l+1); b[q[i].id]=(LL)(q[i].r-q[i].l+1)*(q[i].r-q[i].l); } for (int i=1;i<=m;i++) { //printf("%d %d ",a[i],b[i]); LL k=gcd(a[i],b[i]); if (k!=0) a[i]=a[i]/k; if (k!=0) b[i]=b[i]/k; if (k==0) printf("0/1\n"); else printf("%lld/%lld\n",a[i],b[i]); } } return 0; }
标签:
原文地址:http://www.cnblogs.com/wzb-hust/p/4863669.html