没头脑和不高兴[CTSC2013][期望+线段树]

前言

我是照着老师讲的+这篇博客思路打的…
某大佬的blog

题目

给出 n , m n,m n,m ,一个随机的 1 ∼ n 1\sim n 1n 的排列,现在所有奇数位上有记号,有记号的格子数一开始会自动排序,现在你能从相邻的逆序对随机选择一对交换
Q 1 : Q1: Q1:问排好序的步数的期望和方差?
Q 2 : Q2: Q2:增加区间修改操作(修改格子上的记号),每次修改后询问步数的期望?
1 ≤ n , m ≤ 1 0 5 1\le n,m\le 10^5 1n,m105

思路

发现你选择交换相邻逆序对顺序对答案无影响,每次操作答案即为逆序对个数, ( i , j ) (i,j) (i,j) 是否为逆序对独立,于是:
根据期望线性性可得:

E ( 步 数 ) = E ( 逆 序 对 个 数 ) = ∑ i = 1 n ∑ j = i + 1 n p i j E(步数)=E(逆序对个数)=\sum_{i=1}^n\sum_{j=i+1}^np_{ij} E()=E()=i=1nj=i+1npij

考虑对 p i j p_{ij} pij (i<j) 的计算:

  1. i , j i,j i,j 均无标记
    由于随机, p i j = 1 2 p_{ij}=\frac{1}{2} pij=21
  2. i , j i,j i,j 均有标记
    p i j = 0 p_{ij}=0 pij=0
  3. i i i 有, j j j 没有
    似乎有点难,设有 x x x 个数打标记, i i i 是第 r n k i rnk_i rnki 个数打了标记,我们可以考虑为在有 n n n 个球的盒子里面抓 x + 1 x+1 x+1 个球排好序后随机指定一个为 j j j 所抓的,得出概率为 r n k i x + 1 \frac{rnk_i}{x+1} x+1rnki
  4. j j j 有, i i i 没有
    同理 3 3 3 可得概率为 x + 1 − r n k i x + 1 \frac{x+1-rnk_i}{x+1} x+1x+1rnki

那么考虑计算刚开始的期望:

  1. 长度为偶数 2 n 2n 2n
    E ( X ) = 1 2 ( n 2 ) + ( 1 ∗ n n + 1 + 2 ∗ ( n − 1 ) n + 1 + . . . + n ∗ 1 n + 1 ) + ( ( n + 1 − 2 ) ∗ 1 n + 1 + ( n + 1 − 3 ) ∗ 2 n + 1 + . . . + ( n + 1 − n ) ∗ ( n − 1 ) n + 1 E(X)=\frac{1}{2}\binom{n}{2}+(\frac{1*n}{n+1}+\frac{2*(n-1)}{n+1}+...+\frac{n*1}{n+1})+(\frac{(n+1-2)*1}{n+1}+\frac{(n+1-3)*2}{n+1}+...+\frac{(n+1-n)*(n-1)}{n+1} E(X)=21(2n)+(n+11n+n+12(n1)+...+n+1n1)+(n+1(n+12)1+n+1(n+13)2+...+n+1(n+1n)(n1)
    = n ∗ ( n − 1 ) 4 + ∑ i = 1 n i ∗ ( n − i + 1 ) n + 1 + ∑ i = 1 n − 1 ( n − i ) ∗ i n + 1 =\frac{n*(n-1)}{4}+\sum_{i=1}^{n}\frac{i*(n-i+1)}{n+1}+\sum_{i=1}^{n-1}\frac{(n-i)*i}{n+1} =4n(n1)+i=1nn+1i(ni+1)+i=1n1n+1(ni)i
    = n ∗ ( n − 1 ) 4 + 1 n + 1 ( ( n + 1 ) 2 ∗ n 2 − n ∗ ( n + 1 ) ∗ ( 2 n + 1 ) 6 + ( n − 1 ) ∗ n 2 2 − ( n − 1 ) ∗ n ∗ ( 2 n − 1 ) 6 ) =\frac{n*(n-1)}{4}+\frac{1}{n+1}(\frac{(n+1)^2*n}{2}-\frac{n*(n+1)*(2n+1)}{6}+\frac{(n-1)*n^2}{2}-\frac{(n-1)*n*(2n-1)}{6}) =4n(n1)+n+11(2(n+1)2n6n(n+1)(2n+1)+2(n1)n26(n1)n(2n1))
    = 7 n 2 − n 12 =\frac{7n^2-n}{12} =127n2n
  2. 长度为奇数 2 n + 1 2n+1 2n+1
    E ( X ) = 1 2 ( n 2 ) + ( 1 ∗ n n + 2 + 2 ∗ ( n − 1 ) n + 2 + . . . + 1 ∗ n n + 2 ) + ( ( n + 2 − 2 ) ∗ 1 n + 2 + ( n + 2 − 3 ) ∗ 2 n + 2 + . . . + ( n + 2 − ( n + 1 ) ) ∗ n n + 2 E(X)=\frac{1}{2}\binom{n}{2}+(\frac{1*n}{n+2}+\frac{2*(n-1)}{n+2}+...+\frac{1*n}{n+2})+(\frac{(n+2-2)*1}{n+2}+\frac{(n+2-3)*2}{n+2}+...+\frac{(n+2-(n+1))*n}{n+2} E(X)=21(2n)+(n+21n+n+22(n1)+...+n+21n)+(n+2(n+22)1+n+2(n+23)2+...+n+2(n+2(n+1))n
    = 7 n 2 + n 12 =\frac{7n^2+n}{12} =127n2+n

(真TM难算)
考虑方差计算:
D ( ( x − E ( x ) ) 2 ) = E ( x 2 − 2 x E ( x ) + E ( x ) 2 ) D((x-E(x))^2)=E(x^2-2xE(x)+E(x)^2) D((xE(x))2)=E(x22xE(x)+E(x)2)
= E ( x 2 ) − 2 E ( x E ( x ) ) + E ( x ) 2 =E(x^2)-2E(xE(x))+E(x)^2 =E(x2)2E(xE(x))+E(x)2
= E ( x 2 ) − E ( x ) 2 =E(x^2)-E(x)^2 =E(x2)E(x)2
我们只需要算 E ( x 2 ) E(x^2) E(x2) 即可…
真的不会啊,这 x x x 的分布函数咋求?
好像是利用拉格朗日插值打表
就当这道题练期望吧
方差答案:

长度为偶数 2 n 2n 2n : 54 ∗ n 3 + 13 ∗ n 2 + 23 n 360 \frac{54*n^3+13*n^2+23n}{360} 36054n3+13n2+23n

长度为奇数 2 n + 1 2n+1 2n+1 : 54 ∗ n 3 + 55 ∗ n 2 − 29 n 360 \frac{54*n^3+55*n^2-29n}{360} 36054n3+55n229n

考虑修改操作,情况 1 , 2 1,2 1,2 通过简单的区间操作求出,对于情况 3 , 4 3,4 3,4 考虑每一个未标记位置 i i i 对答案的贡献:

  1. j < i j<i j<i j j j 被标记
    i i i 前面有 k k k 个位置被标记,当前总标记为 x x x
    那么 i i i 对答案的贡献为 ∑ i = 1 k i x + 1 = 1 x + 1 ∗ k ∗ ( k + 1 ) 2 \sum_{i=1}^k\frac{i}{x+1}=\frac{1}{x+1}*\frac{k*(k+1)}{2} i=1kx+1i=x+112k(k+1)
    然后就是高端操作了…
    难点在计算 k ∗ ( k + 1 ) 2 \frac{k*(k+1)}{2} 2k(k+1)
    发现 k ∗ ( k + 1 ) 2 = k ∗ ( k − 1 ) 2 + k = ( k 2 ) + k \frac{k*(k+1)}{2}=\frac{k*(k-1)}{2}+k=\binom{k}{2}+k 2k(k+1)=2k(k1)+k=(2k)+k
    记标记位置为 1 1 1 ,没有为 0 0 0 ,实际上统计 110 110 110 10 10 10 的个数
  2. i < j i<j i<j j j j 被标记
    差不多,设 i i i 后面有 k k k 个位置被标记
    那么 i i i 对答案的贡献为 ∑ i = x + 1 − k x x + 1 − i x + 1 = ∑ i = 1 k i x + 1 = 1 x + 1 ∗ k ∗ ( k + 1 ) 2 \sum_{i=x+1-k}^x\frac{x+1-i}{x+1}=\sum_{i=1}^k\frac{i}{x+1}=\frac{1}{x+1}*\frac{k*(k+1)}{2} i=x+1kxx+1x+1i=i=1kx+1i=x+112k(k+1)
    即统计 011 011 011 01 01 01 的个数

线段树即可 1 , 2 1,2 1,2 通过统计 0 , 1 0,1 0,1 个数能求出

代码

#include<map>
#include<set>
#include<stack>
#include<queue>
#include<cmath>
#include<cstring>
#include<climits>
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
//#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
//char buf[(1 << 21) + 1], *p1 = buf, *p2 = buf;
inline int read() {
	bool f=0;int x=0;char c=getchar();
	while(c<'0'||'9'<c){if(c==EOF)exit(0);if(c=='-')f=1;c=getchar();}
	while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
	return !f?x:-x;
}
#define MAXN 100000
#define INF 0x3f3f3f3f
LL gcd(LL a,LL b){return !b?a:gcd(b,a%b);}
struct node{
	int l,r,lazy;
	LL cnt_0,cnt_1,cnt_01,cnt_10,cnt_011,cnt_110;
	friend node operator + (node a,node b){
		node c;
		c.l=a.l,c.r=b.r,c.lazy=-1;
		c.cnt_0=a.cnt_0+b.cnt_0;
		c.cnt_1=a.cnt_1+b.cnt_1;
		c.cnt_01=a.cnt_01+b.cnt_01+a.cnt_0*b.cnt_1;
		c.cnt_10=a.cnt_10+b.cnt_10+a.cnt_1*b.cnt_0;
		c.cnt_011=a.cnt_011+b.cnt_011+a.cnt_01*b.cnt_1+a.cnt_0*b.cnt_1*(b.cnt_1-1)/2;
		c.cnt_110=a.cnt_110+b.cnt_110+a.cnt_1*b.cnt_10+a.cnt_1*(a.cnt_1-1)/2*b.cnt_0;
		return c;
	}
}tree[5*MAXN+5];
#define lch (u<<1)
#define rch (u<<1|1)
void PushUp(int u){
	tree[u]=tree[lch]+tree[rch];
	return ;
}
void PushDown(int u,int L,int Mid,int R){
	if(tree[u].lazy==-1) return ;
	tree[lch]=(node){L,Mid,tree[u].lazy,(Mid-L+1)*(tree[u].lazy^1),(Mid-L+1)*tree[u].lazy,0,0,0,0};
	tree[rch]=(node){Mid+1,R,tree[u].lazy,(R-Mid)*(tree[u].lazy^1),(R-Mid)*tree[u].lazy,0,0,0,0};
	tree[u].lazy=-1;
	return ;
}
void Build(int u,int L,int R){
	if(L==R){
		tree[u]=(node){L,R,-1,(L&1)^1,(L&1),0,0,0,0};
		return ;
	}
	int Mid=(L+R)>>1;
	Build(lch,L,Mid),Build(rch,Mid+1,R);
	PushUp(u);
	return ;
}
void Modify(int u,int L,int R,int qL,int qR,int v){
	if(qL<=L&&R<=qR){
		tree[u]=(node){L,R,v,(R-L+1)*(v^1),(R-L+1)*v,0,0,0,0};
		return ;
	}
	int Mid=(L+R)>>1;
	PushDown(u,L,Mid,R);
	if(qL<=Mid)
		Modify(lch,L,Mid,qL,qR,v);
	if(Mid+1<=qR)
		Modify(rch,Mid+1,R,qL,qR,v);
	PushUp(u);
	return ;
}
int main(){
	LL n=read(),x=n/2,m=read();
	if(n&1){
		LL p=7*x*x+x,q=12,g=gcd(p,q);
		printf("%lld/%lld\n",p/g,q/g);
		p=54*x*x*x+55*x*x-29*x,q=360,g=gcd(p,q);
		printf("%lld/%lld\n",p/g,q/g);
	}
	else{
		LL p=7*x*x-x,q=12,g=gcd(p,q);
		printf("%lld/%lld\n",p/g,q/g);
		p=54*x*x*x+13*x*x+23*x,q=360,g=gcd(p,q);
		printf("%lld/%lld\n",p/g,q/g);
	}
	Build(1,1,n);
	for(int i=1;i<=m;i++){
		int l=read(),r=read(),v=read();
		Modify(1,1,n,l,r,v);
		node Rt=tree[1];
		LL p1=Rt.cnt_01+Rt.cnt_011+Rt.cnt_10+Rt.cnt_110,q1=Rt.cnt_1+1;
		LL p2=Rt.cnt_0*(Rt.cnt_0-1),q2=4;
		LL p=p1*q2+p2*q1,q=q1*q2,g=gcd(p,q);
		printf("%lld/%lld\n",p/g,q/g);
	}
	return 0;
}

题外话

CF的k不相交子段和的18个变量教会我做人,这题实际做法跟那道比起来太简单了…

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值