[BZOJ 2038]小Z的袜子
转载请注明出处:http://danihao123.is-programmer.com/
今年第一更……噫
终于学会莫队了,不过目前只能做这样的模板题……
代码:
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <utility>
using namespace std;
const int maxn=50005;
typedef long long ll;
ll gcd(ll a,ll b){
if(!b){
return a;
}else{
return gcd(b,a%b);
}
}
ll C2(ll n){
register ll temp,ns1=n-1;
if(n&1){
temp=ns1>>1;
return temp*n;
}else{
temp=n>>1;
return temp*ns1;
}
}
struct Node{
int L_s;
int L,R;
int id;
ll ans1,ans2;
};
bool cmp1(const Node& a,const Node& b){
if(a.L_s==b.L_s){
return a.R<b.R;
}else{
return a.L_s<b.L_s;
}
}
bool cmp2(const Node& a,const Node& b){
return a.id<b.id;
}
Node Q[maxn];
int C[maxn],d[maxn];
int n,m;
inline void add_p(int x,ll &ans){
d[x]++;
ans+=d[x]-1;
}
inline void sub_p(int x,ll &ans){
d[x]--;
ans-=d[x];
}
inline void Mo(){
register int i,j,L_p,R_p,sqrt_n=sqrt(n+0.5);
register ll ans,t_gcd,t2;
for(i=1;i<=m;i++){
Q[i].L_s=Q[i].L/sqrt_n;
}
sort(Q+1,Q+1+m,cmp1);
L_p=R_p=Q[1].L;
ans=0;
d[C[L_p]]++;
for(i=1;i<=m;i++){
while(L_p<Q[i].L){
sub_p(C[L_p],ans);
L_p++;
}
while(L_p>Q[i].L){
L_p--;
add_p(C[L_p],ans);
}
while(R_p<Q[i].R){
R_p++;
add_p(C[R_p],ans);
}
while(R_p>Q[i].R){
sub_p(C[R_p],ans);
R_p--;
}
t2=C2(R_p-L_p+1);
t_gcd=gcd(ans,t2);
Q[i].ans1=ans/t_gcd;
Q[i].ans2=t2/t_gcd;
}
sort(Q+1,Q+1+m,cmp2);
}
int main(){
register int i;
int a,b;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++){
scanf("%d",&C[i]);
}
for(i=1;i<=m;i++){
Q[i].id=i;
scanf("%d%d",&a,&b);
Q[i].L=a;
Q[i].R=b;
}
Mo();
for(i=1;i<=m;i++){
printf("%lld/%lld\n",Q[i].ans1,Q[i].ans2);
}
return 0;
}
评论 (0)