冲刺国赛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;
}
基础树论练习题
咕咕咕