冲刺国赛6.28

又充值了 \(1\) 个月,那就写写博客吧

基础概率练习题

重新体会了概率,题解写的很好于是就复读一遍

\(P(A|B)=\frac{P(AB)}{P(B)}\)\(B\) 发生的情况下 \(A\) 发生的概率,等于 \(A,B\) 同时发生的概率除以 \(B\) 发生的概率

对应到这个题的话,\(A\) 就是第一个是最大值,\(B\) 就是第一个大于等于 \(k\)

又发现对于每一个人的 \(P(AB)\) 是相同的

那么 \(n\times P(AB)\) 就相当于至少一个大于等于 \(k\) 的情况除以所有的情况

至少一个大于等于 \(k\) 的方案数可以容斥求出

Code
#include<bits/stdc++.h>
#define int long long
#define mod 998244353
#define inf 0x3f3f3f3f3f3f3f3f
#define meow(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,m,k,ans;
int fac[20000010],inv[20000010];
inline int C(int n,int m){return fac[n]*inv[m]%mod*inv[n-m]%mod;}
inline int qpow(int x,int k){
	int res=1,base=x;
	while(k){if(k&1) res=res*base%mod;base=base*base%mod;k>>=1;}
	return res;
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("probability.in","r",stdin);
	freopen("probability.out","w",stdout);
	n=read(),m=read(),k=read();
	inv[0]=fac[0]=1;for(int i=1;i<=20000000;i++) fac[i]=fac[i-1]*i%mod;
	inv[20000000]=qpow(fac[20000000],mod-2);
	for(int i=19999999;i;i--) inv[i]=inv[i+1]*(i+1)%mod;
	for(int i=1,r=1;i<=n&&i*k<=m;i++,r=-r) ans=(ans+r*C(n,i)*C(m-i*k+n-1,n-1)%mod+mod)%mod;
	printf("%lld\n",ans*qpow(n,mod-2)%mod*qpow(C(n+m-1-k,n-1),mod-2)%mod);
	return 0;
}

基础树剖练习题

赛时只会链查询,不会子树,赛后又编了个做法做子树的查询

链的做法,把边放到儿子上维护,比较经典

维护每一条重链的信息,然后跳链时再维护链与链之间的信息

具体做法是维护一个 \(tag\) 表示线段树上这个区间被覆盖时右端点的颜色是黑色还是白色

有了这个信息就能快速维护区间的黑边个数

跳链时修改链的哪一个儿子的颜色不同就行

子树的做法,把边放到父亲上维护

\(tag\) 和上面的共用一个,预处理出每个区间右端点为哪种颜色时区间的黑边数量

还有亿些细节

两个做法都需要对修改的点 \(x\) 特殊处理一下

做链时需要对重儿子修改

Code
#include<bits/stdc++.h>
// #define int long long
#define lson rt<<1
#define rson rt<<1|1
#define inf 0x3f3f3f3f3f3f3f3f
#define meow(args...) fprintf(stderr,args)
using namespace std;
inline int read(){
	int x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	return x*f;
}
int n,q;
int b[100010];
int fa[100010],dep[100010],dfn[100010],siz[100010],son[100010],top[100010],bot[100010],d[100010],clo;
int head[100010],ver[100010],to[100010],tot;
struct seg{
	int sum,atag,len,son;//0 白色结尾 1 黑色结尾
	int pre[2],zs;
}st[100010*4];
inline void add(int x,int y){ver[++tot]=y;to[tot]=head[x];head[x]=tot;}
inline void pushup(int rt){st[rt].sum=st[lson].sum+st[rson].sum;st[rt].zs=st[lson].zs+st[rson].zs;}
inline void pushdown(int rt){
	if(~st[rt].atag){
		st[rson].atag=st[rt].atag;
		st[lson].son=st[rson].son=0;
		st[lson].atag=st[rt].atag^(st[rson].len&1);
		st[lson].sum=(st[lson].len+st[lson].atag)>>1;
		st[rson].sum=(st[rson].len+st[rson].atag)>>1;
		st[lson].zs=st[lson].pre[st[lson].atag];
		st[rson].zs=st[rson].pre[st[rson].atag];
		st[rt].atag=-1;
	}
}
void build(int rt,int l,int r){
	st[rt].atag=-1,st[rt].len=r-l+1;if(l==r) return st[rt].atag=0,st[rt].pre[1]=(d[b[l]]-1),st[rt].pre[0]=(d[b[l]]!=0),void();
	int mid=(l+r)>>1;
	build(lson,l,mid);
	build(rson,mid+1,r);
	st[rt].pre[0]=st[rson].pre[0]+st[lson].pre[0^(st[rson].len&1)];
	st[rt].pre[1]=st[rson].pre[1]+st[lson].pre[1^(st[rson].len&1)];
}
void upd(int rt,int l,int r,int L,int R,int k){
	if(L<=l&&r<=R) return st[rt].atag=k,st[rt].sum=(st[rt].len+k)>>1,st[rt].zs=st[rt].pre[k],st[rt].son=0,void();
	int mid=(l+r)>>1;pushdown(rt);
	if(R<=mid) upd(lson,l,mid,L,R,k);
	else if(L>mid) upd(rson,mid+1,r,L,R,k);
	else upd(lson,l,mid,L,mid,k^(R-mid&1)),upd(rson,mid+1,r,mid+1,R,k);
	pushup(rt);
}
void mdf(int rt,int l,int r,int pos,int k,int typ){
	if(l==r){
		if(typ==1) st[rt].son=k;
		if(typ==2) st[rt].sum=k;
		if(typ==3) st[rt].zs++;
		return ;
	}
	int mid=(l+r)>>1;pushdown(rt);
	if(pos<=mid) mdf(lson,l,mid,pos,k,typ);
	else mdf(rson,mid+1,r,pos,k,typ);
	pushup(rt);
}
int query(int rt,int l,int r,int L,int R,int typ){
	if(L<=l&&r<=R) return typ?st[rt].sum:st[rt].zs;
	int mid=(l+r)>>1,res=0;pushdown(rt);
	if(L<=mid) res+=query(lson,l,mid,L,R,typ);
	if(R>mid) res+=query(rson,mid+1,r,L,R,typ);
	return res;
}
pair<int,int> qry(int rt,int l,int r,int pos){
	if(l==r) return make_pair(st[rt].atag,st[rt].son);
	int mid=(l+r)>>1;pushdown(rt);
	if(pos<=mid) return qry(lson,l,mid,pos);
	else return qry(rson,mid+1,r,pos);
}
inline void Tupd(int x){
	int lst=0,k=1;
	while(top[x]){
		upd(1,1,n,dfn[top[x]],dfn[x],k);
		if(lst) mdf(1,1,n,dfn[x],lst,1);else if(bot[top[x]]!=x) mdf(1,1,n,dfn[x]+1,1,2);
		if(lst==0) mdf(1,1,n,dfn[x],0,3);else if(bot[top[x]]!=x) mdf(1,1,n,dfn[x]+1,k,2);
		k^=((dfn[top[x]]-dfn[x]+1)&1);
		lst=top[x],x=fa[top[x]];
	}
}
inline int Tquery(int x){
	int res=0;pair<int,int>tmp;
	while(top[x]){
		if(dfn[top[x]]+1<=dfn[x]) res+=query(1,1,n,dfn[top[x]]+1,dfn[x],1);
		if(top[x]!=1){
			tmp=qry(1,1,n,dfn[fa[top[x]]]);
			res+=tmp.first^(tmp.second==top[x]);
		}
		x=fa[top[x]];
	}
	return res;
}
void dfs1(int x,int fa,int dep){
	::dep[x]=dep,siz[x]=1;
	int maxson=-1;
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];d[x]++;
		dfs1(y,x,dep+1);siz[x]+=siz[y];
		if(siz[y]>maxson) son[x]=y,maxson=siz[y];
	}
}
void dfs2(int x,int topf){
	top[x]=topf,dfn[x]=++clo,bot[topf]=x,b[clo]=x;
	if(!son[x]) return ;
	dfs2(son[x],topf);
	for(int i=head[x];i;i=to[i]){
		int y=ver[i];if(y==son[x]) continue;
		dfs2(y,y);
	}
}
signed main(){
#ifdef LOCAL
	freopen("in","r",stdin);
	freopen("out","w",stdout);
#endif
	freopen("chain.in","r",stdin);
	freopen("chain.out","w",stdout);
	n=read();
	for(int i=2;i<=n;i++) add(fa[i]=read(),i);
	dfs1(1,0,1),dfs2(1,1);
	build(1,1,n);
	q=read();
	for(int i=1,op,x;i<=q;i++){
		op=read(),x=read();
		if(op==1) Tupd(x);
		if(op==2) printf("%d\n",Tquery(x));
		if(op==3) printf("%d\n",query(1,1,n,dfn[x],dfn[x]+siz[x]-1,0));
	}
	return 0;
}

基础树论练习题

咕咕咕

posted @ 2022-06-28 19:58  Max_QAQ  阅读(58)  评论(0编辑  收藏  举报