bzoj2038: [2009国家集训队]小Z的袜子(hose)
拍了一早上结果是LL的问题。。。c,%%%rose大佬rp++
昨天珂谷模拟赛,大佬们T2都带修莫队65,就我一个暴力40(要是这题+25就机房rank1了。。。)亡羊补牢一下。
化简一下式子 (a^2+b^2+c^2……)-(r-l+1) / (r-l+1)*(r-.l)
然后就是分块,排序,之后每次询问用sqrt(n)就OK
#include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> using namespace std; typedef long long LL; struct node { int l,r,id; LL fz,fm; }a[51000]; int fk,st[51000]; bool cmp(node n1,node n2) { if(st[n1.l]<st[n2.l]||(st[n1.l]==st[n2.l]&&st[n1.r]<st[n2.r]))return true; return false; } bool cmd(node n1,node n2) { if(n1.id<n2.id)return true; return false; } int n,m,c[51000];LL ans,s[51000]; void update(int i,int k) { ans-=s[c[i]]*s[c[i]]; s[c[i]]+=k; ans+=s[c[i]]*s[c[i]]; } LL gcd(LL a,LL b) { if(a==0)return b; return gcd(b%a,a); } void solve() { int l=1,r=0;ans=0; memset(s,0,sizeof(s)); for(int i=1;i<=m;i++) { while(r<a[i].r)r++, update(r,1); while(r>a[i].r)update(r,-1), r--; while(l<a[i].l)update(l,-1), l++; while(l>a[i].l)l--, update(l,1); if(a[i].l==a[i].r){a[i].fz=0,a[i].fm=1;continue;} a[i].fz=ans-(a[i].r-a[i].l+1); a[i].fm=(LL)(a[i].r-a[i].l+1)*(LL)(a[i].r-a[i].l); LL k=gcd(a[i].fz,a[i].fm); a[i].fz/=k;a[i].fm/=k; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<=m;i++)scanf("%d%d",&a[i].l,&a[i].r), a[i].id=i; fk=int(sqrt(n)); for(int i=1;i<=n;i++)st[i]=(i-1)/fk+1; sort(a+1,a+m+1,cmp); solve(); sort(a+1,a+m+1,cmd); for(int i=1;i<=m;i++)printf("%lld/%lld\n",a[i].fz,a[i].fm); return 0; }
pain and happy in the cruel world.