考虑两个纸牌i和j满足i<j,那么如果a[i]>a[j]则对答案有贡献为1;分四种情况讨论:
1.i和j都没被排序,期望贡献1/2;2.i和j都被排序,期望贡献0;
3.只有i被排序,假设被排序的有t个数,那么在期望情况下这t个数是均匀分布的,则a[j]比a[i]小的概率为Pi/(t+1),Pi表示i在t个数中是第几个;
4.同理只有j被排序时期望为(t-Pi+1)/(t+1);
这样分4中情况就可算出期望的公式;当N=2n时为(7n^2+n)/12,N=2n+1时为(7n^2-n)/12。
修改的话考虑用线段树维护区间修改。显然情况1和2是容易维护的;对于所有没有被排序的位置i,如果i前面有k个被排序,而总共有t个被排序的数,那么对于第三种情况答案就是1/(t+1)+2/(t+1)+...+k/(t+1)=(k^2+k)/2(t+1);第四种情况就是1/(t+1)+...+(t-k)/(t+1)=((t-k)^2+t-k)/2(t+1)。注意到分母相同,也就是说我们只需要维护所有i的k^2+k+(t-k)^2+t-k的和即可,拆开来之后可以考虑分别维护k^2和k的和。
然后还要求方差。。。你可以假设答案次数不是很大然后暴力出几组数据然后拉格朗日差值。。。不过我是直接抄艾神公式的。。N=2n时为(54n^3+13n^2+23n)/360;N=2n+1时为(54n^3+55n^2-29n)/360
AC代码如下:
#include<iostream> #include<cstdio> #define ll long long #define N 300005 using namespace std; int n,m,tx,ty,tz,tg[N]; struct node{ int s0,s1; ll x,y; }val[N]; ll gcd(ll x,ll y){ return (y)?gcd(y,x%y):x; } int read(){ int x=0; char ch=getchar(); while (ch<'0' || ch>'9') ch=getchar(); while (ch>='0' && ch<='9'){ x=x*10+ch-'0'; ch=getchar(); } return x; } void opt(ll x,ll y){ ll d=gcd(x,y); printf("%lld/%lld\n",x/d,y/d); } struct frc{ ll x,y; frc(){} frc(ll u,ll v){ ll d=gcd(u,v); x=u/d; y=v/d; } }ans; frc operator +(frc u,frc v){ ll d=gcd(u.y,v.y),fm=u.y/d*v.y; return frc(fm/u.y*u.x+fm/v.y*v.x,fm); } void maintain(int k){ int l=k<<1,r=l|1; val[k].s0=val[l].s0+val[r].s0; val[k].s1=val[l].s1+val[r].s1; val[k].x=val[l].x+val[r].x+(ll)val[l].s1*val[l].s1*val[r].s0+(val[r].y*val[l].s1<<1); val[k].y=val[l].y+val[r].y+(ll)val[l].s1*val[r].s0; } void cvr(int k,int v){ if (!v){ val[k].s0+=val[k].s1; val[k].s1=0; } else{ val[k].s1+=val[k].s0; val[k].s0=0; } val[k].x=val[k].y=0; tg[k]=v; } void pushdown(int k){ if (tg[k]!=-1){ cvr(k<<1,tg[k]); cvr(k<<1|1,tg[k]); tg[k]=-1; } } void build(int k,int l,int r){ tg[k]=-1; if (l==r){ if (l&1) val[k].s1=1; else val[k].s0=1; return; } int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); maintain(k); } void mdy(int k,int l,int r){ if (tx<=l && r<=ty){ cvr(k,tz); return; } pushdown(k); int mid=(l+r)>>1; if (tx<=mid) mdy(k<<1,l,mid); if (ty>mid) mdy(k<<1|1,mid+1,r); maintain(k); } int main(){ n=read(); m=read(); int t=n>>1; if (n&1){ opt(((ll)t*7+1)*t,12); opt((((ll)t*54+55)*t-29)*t,360); } else{ opt(((ll)t*7-1)*t,12); opt((((ll)t*54+13)*t+23)*t,360); } build(1,1,n); while (m--){ tx=read(); ty=read(); tz=read(); mdy(1,1,n); ans=frc((ll)val[1].s0*(val[1].s0-1),4); ans=ans+frc(((ll)val[1].s1*val[1].s1+val[1].s1)*val[1].s0,(val[1].s1+1)<<1); ans=ans+frc((val[1].x-val[1].y*val[1].s1)<<1,(val[1].s1+1)<<1); printf("%lld/%lld\n",ans.x,ans.y); } return 0; }
by lych
2016.5.25