CF每日3题(1600)
省流:
- 2129B 贪心找最少逆序对
- 2128D dp找所有子数组LDS长度和
- 2125D 概率dp
2129B 贪心 1600
参考题解
题意:给一组排序,保持原样或反转变成2n−pi2n-p_i2n−pi,让逆序对数量最小化
- 排列pi≤np_i\leq npi≤n,那么2n−pi≥n2n-p_i\geq n2n−pi≥n
- pip_ipi保持原样
- 前面的数若j<i,pj>pij<i,p_j>p_ij<i,pj>pi,形成逆序对
- 后面的逆序对会在之后的循环中计算
- pip_ipi变成2n−pi2n-p_i2n−pi
- 前面的数不会和2n−pi2n-p_i2n−pi逆序
- 后面的数尽量反转,若i<j,pi<pj,2n−pi>2n−pj>pji<j,p_i<p_j,2n-p_i>2n-p_j>p_ji<j,pi<pj,2n−pi>2n−pj>pj
void solve(){int n;cin>>n;vector<int>p(n+1);forr(i,1,n)cin>>p[i];//O(n2)可接受int ans=0;forr(i,2,n){int pre=0,suf=0;forr(j,1,i-1)pre+=(p[j]>p[i]);//本次不反转forr(j,i+1,n)suf+=(p[j]>p[i]);//本次反转 后面的尽量都要反转以避免产生逆序对 //但是如果j>i p[j]>p[i] p[j]<2n-p[j]<2n-p[i] 那就没办法了 一定会有逆序对ans+=min(pre,suf);//看反转还是不反转比较好}cout<<ans<<endl;
}
2128D dp 1600
题意:找所有子数组(数组连续一段)中最大LDS长度和
dp[i][j]dp[i][j]dp[i][j]是以pip_ipi为结尾,长度为jjj的子数组(j≤i)(j\leq i)(j≤i)
- 若pi−1>pip_{i-1}>p_ipi−1>pi,形成LDS,dp[i][j]=dp[i−1][j−1]+1又dp[i]=∑j=1idp[i][j]=∑j=1idp[i−1][j−1]+i=dp[i−1]+idp[i]=dp[i−1]+idp[i][j]=dp[i-1][j-1]+1\\又dp[i]=\sum \limits_{j=1}^i dp[i][j]=\sum \limits_{j=1}^idp[i-1][j-1]+i=dp[i-1]+i\\dp[i]=dp[i-1]+idp[i][j]=dp[i−1][j−1]+1又dp[i]=j=1∑idp[i][j]=j=1∑idp[i−1][j−1]+i=dp[i−1]+idp[i]=dp[i−1]+i
- 若pi−1<pi,由题max(pi−2,pi−1)>pi,pi−2>pi>pi−1p_{i-1}<p_i,由题max(p_{i-2},p_{i-1})>p_i,p_{i-2}>p_i>p_{i-1}pi−1<pi,由题max(pi−2,pi−1)>pi,pi−2>pi>pi−1,从pi−2p_{i-2}pi−2转移过来dp[i][j]=dp[i−2][j−1]+1dp[i]=∑j=1idp[i][j]=(∑j=1idp[i−2][j−1]+i−1)+1=dp[i−1]+1dp[i][j]=dp[i-2][j-1]+1\\dp[i]=\sum \limits_{j=1}^i dp[i][j]=(\sum \limits_{j=1}^idp[i-2][j-1]+i-1)+1=dp[i-1]+1dp[i][j]=dp[i−2][j−1]+1dp[i]=j=1∑idp[i][j]=(j=1∑idp[i−2][j−1]+i−1)+1=dp[i−1]+1
void solve(){int n;cin>>n;vector<int>dp(n+1);vector<int>p(n+1);forr(i,1,n)cin>>p[i];dp[1]=1;forr(i,2,n){if(p[i]<p[i-1])dp[i]=i+dp[i-1];else dp[i]=dp[i-1]+1;}int sm=0;forr(i,1,n)sm+=dp[i];cout<<sm<<endl;
}
2125D 概率dp 数学 1600
参考题解
题意:找每个格子恰好被一条线段覆盖的概率
- 恰好一条线段,其他不覆盖×一条覆盖
- dp[ri]=dp[li−1]+probi∏(1−probothers)dp[r_i]=dp[l_i-1]+prob_i\prod(1-prob_{others})dp[ri]=dp[li−1]+probi∏(1−probothers)
- 其他不覆盖概率的可以用前缀积得出
const int N=2e5+10,mod=998244353;
struct seg
{int l,r;int pro;
}a[N];
/*
dp[i]以a[i].r结尾的答案
ex[i]a[i].r什么都不选的概率
*/
int dp[N],ex[N];
int qpow(int x,int a){int res=1;while (a){ if(a&1)res*=x,res%=mod;a>>=1;x*=x,x%=mod;}return res%mod;
}
int inv(int x){return qpow(x,mod-2)%mod;
}
void solve(){int n,m;cin>>n>>m;forr(i,0,m)ex[i]=1;forr(i,1,n){int p,q;cin>>a[i].l>>a[i].r>>p>>q;a[i].pro=p*inv(q)%mod;ex[a[i].l]=ex[a[i].l]*(1-a[i].pro+mod)%mod;}forr(i,1,m)ex[i]=ex[i]*ex[i-1]%mod;//前缀积 可用来求区间中什么都不选的概率sort(a+1,a+n+1,[](seg x,seg y){return x.l<y.l;});dp[0]=1;forr(i,1,n){int tp=dp[a[i].l-1];tp=tp*ex[a[i].r]%mod*inv(ex[a[i].l-1])%mod;//l~r什么都不覆盖的概率tp=tp*inv(1-a[i].pro+mod)%mod;//除了i线段其他什么都没有的概率tp=tp*a[i].pro%mod;//只覆盖i线段dp[a[i].r]=(dp[a[i].r]+tp)%mod;}// forr(i,1,m)cout<<dp[i]<<' ';cout<<endl;cout<<dp[m]<<endl;
}