1265D Beautiful Sequence(构造 贪心)
题意:
给你若干数量的0、1、2、3,用完所有的数字构造一个序列使得任意相邻两数相差恰好为1。
解法:
首先确定0和2的相对位置如下:0,0,0,……,0,0,2,2,……,2,2。此时1可放在任意两数之间,3只能放在两个2之间或放在最右侧,故只要最大化可以放3的放置,剩余位放1即可。
于是有以下的贪心策略:以最小或次小的数作为首项,设前一位放置数字x,若x-1的数量不为0就放置x-1,否则放置x+1,若x+1的数量为0则无解。
复杂度: O ( n ) O(n) O(n)。
#include<bits/stdc++.h>
using namespace std;
const int maxn=1e5+5;
int ans[maxn],a[5],tmp[5];
bool check(int fst,int n)
{
int pt=fst;
for(int i=0;i<4;i++)
tmp[i]=a[i];
if(!tmp[fst]) return false;
for(int i=1;i<=n;i++)
{
ans[i]=pt,tmp[pt]--;
if(i==n) break;
if(pt&&tmp[pt-1]) pt--;
else if(tmp[pt+1]) pt++;
else return false;
}
return true;
}
int main()
{
int n=0;
for(int i=0;i<4;i++)
scanf("%d",&a[i]),n+=a[i];
for(int i=0;i<4;i++) if(check(i,n))
{
puts("YES");
for(int j=1;j<=n;j++)
printf("%d ",ans[j]);
return 0;
}
puts("NO");
}
1265F Beautiful Bracket Sequence (ev)(区间DP)
题意:
给一个仅由’?’、’(’、’)‘组成的字符串S,其中每一个’?‘均可被替换为’(’、’)’,求所有可能的全部’?'被替换后形成的字符串的括号嵌套深度之和,替换后形成的字符串不一定是合法的括号序列 ( ∣ S ∣ ≤ 2000 ) (|S|\le2000) (∣S∣≤2000)。
解法:
考虑区间DP,设 d p [ l ] [ r ] dp[l][r] dp[l][r]为串 S l , S l + 1 , . . . , S r − 1 , S r S_l,S_{l+1},...,S_{r-1},S_r Sl,Sl+1,...,Sr−1,Sr替换后形成的所有串的括号嵌套深度之和。现求 d p [ l ] [ r ] dp[l][r] dp[l][r]的值,对 S l S_l Sl、 S r S_r Sr进行讨论,有如下的转移方程:
- 若 S l = = ′ ) ′ S_l==')' Sl==′)′,则 S l S_l Sl一定不对答案产生贡献: d p [ l ] [ r ] = d p [ l + 1 ] [ r ] dp[l][r]=dp[l+1][r] dp[l][r]=dp[l+1][r];
- 若 S r = = ′ ( ′ S_r=='(' Sr==′(′,同理有: d p [ l ] [ r ] = d p [ l ] [ r − 1 ] dp[l][r]=dp[l][r-1] dp[l][r]=dp[l][r−1];
- 若 S l = = ′ ( ′ S_l=='(' Sl==′(′且 S r = = ′ ) ′ S_r==')' Sr==′)′,我们已知 d p [ l + 1 ] [ r − 1 ] dp[l+1][r-1] dp[l+1][r−1],仅需考虑 S l S_l Sl、 S r S_r Sr两端对答案的贡献。设 T = S l + 1 , S l + 2 , . . . , S r − 2 , S r − 1 T=S_{l+1},S_{l+2},...,S_{r-2},S_{r-1} T=Sl+1,Sl+2,...,Sr−2,Sr−1,k为T中’?‘的数量,则当T中所有的’?'被替换后将形成 2 k 2^k 2k种不同的串,故 S l S_l Sl、 S r S_r Sr的贡献为 2 k 2^k 2k: d p [ l ] [ r ] = d p [ l + 1 ] [ r − 1 ] + 2 k dp[l][r]=dp[l+1][r-1]+2^k dp[l][r]=dp[l+1][r−1]+2k;
- 若 S l = = ′ ? ′ S_l=='?' Sl==′?′且 S r = = ′ ) ′ S_r==')' Sr==′)′, S l S_l Sl能被替换为’(‘或’)’,故产生两种新串。当 S l = = ′ ) ′ S_l==')' Sl==′)′时,整个串对答案的贡献同1. ,为 d p [ l + 1 ] [ r ] dp[l+1][r] dp[l+1][r];当 S l = = ′ ( ′ S_l=='(' Sl==′(′时,整个串对答案的贡献同3. ,为 d p [ l + 1 ] [ r − 1 ] + 2 k dp[l+1][r-1]+2^k dp[l+1][r−1]+2k。因此有: d p [ l ] [ r ] = d p [ l + 1 ] [ r ] + d p [ l + 1 ] [ r − 1 ] + 2 k dp[l][r]=dp[l+1][r]+dp[l+1][r-1]+2^k dp[l][r]=dp[l+1][r]+dp[l+1][r−1]+2k;
- 若 S l = = ′ ( ′ S_l=='(' Sl==′(′且 S r = = ′ ? ′ S_r=='?' Sr==′?′,分析同上有: d p [ l ] [ r ] = d p [ l ] [ r − 1 ] + d p [ l + 1 ] [ r − 1 ] + 2 k dp[l][r]=dp[l][r-1]+dp[l+1][r-1]+2^k dp[l][r]=dp[l][r−1]+dp[l+1][r−1]+2k;
- 若 S l = = ′ ? ′ S_l=='?' Sl==′?′且 S r = = ′ ? ′ S_r=='?' Sr==′?′,产生四种新串。当 S l = = ′ ) ′ S_l==')' Sl==′)′时, S r = = ′ ( ′ S_r=='(' Sr==′(′和 S r = = ′ ) ′ S_r==')' Sr==′)′两种串产生的贡献之和为 d p [ l ] [ r − 1 ] dp[l][r-1] dp[l][r−1];同理,当 S r = = ′ ( ′ S_r=='(' Sr==′(′时, S l = = ′ ( ′ S_l=='(' Sl==′(′和 S l = = ′ ) ′ S_l==')' Sl==′)′两种串产生的贡献之和为 d p [ l + 1 ] [ r ] dp[l+1][r] dp[l+1][r]。根据上述讨论我们将 S l = = ′ ) ′ S_l==')' Sl==′)′且 S r = = ′ ( ′ S_r=='(' Sr==′(′的情况计算了两次,但没计算 S l = = ′ ( ′ S_l=='(' Sl==′(′且 S r = = ′ ) ′ S_r==')' Sr==′)′的情况。再由3. 的分析,我们得到当 S l = = ′ ( ′ S_l=='(' Sl==′(′且 S r = = ′ ) ′ S_r==')' Sr==′)′时的贡献为 d p [ l + 1 ] [ r − 1 ] + 2 k dp[l+1][r-1]+2^k dp[l+1][r−1]+2k,而 d p [ l + 1 ] [ r − 1 ] dp[l+1][r-1] dp[l+1][r−1]其实就是当 S l = = ′ ) ′ S_l==')' Sl==′)′且 S r = = ′ ( ′ S_r=='(' Sr==′(′时的贡献。综上有: d p [ l ] [ r ] = d p [ l ] [ r − 1 ] + d p [ 1 + 1 ] [ r ] + 2 k dp[l][r]=dp[l][r-1]+dp[1+1][r]+2^k dp[l][r]=dp[l][r−1]+dp[1+1][r]+2k。
复杂度: O ( n 2 ) O(n^2) O(n2)。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e3+5;
const ll mod=998244353;
ll dp[maxn][maxn],cnt[maxn],pow2[maxn]={1};
char s[maxn];
int main()
{
cin>>(s+1);
int n=strlen(s+1);
for(int i=1;i<=n;i++)
cnt[i]=cnt[i-1]+(s[i]=='?'),pow2[i]=(pow2[i-1]<<1)%mod;
for(int i=2;i<=n;i++)
for(int l=1,r=l+i-1;r<=n;l++,r++)
{
ll &x=dp[l][r],p=pow2[cnt[r-1]-cnt[l]];
x=dp[l+1][r-1];
if(s[l]==')') x=dp[l+1][r];
if(s[r]=='(') x=dp[l][r-1];
if(s[l]=='('&&s[r]==')') x=dp[l+1][r-1]+p;
if(s[l]=='?'&&s[r]==')') x=dp[l+1][r]+dp[l+1][r-1]+p;
if(s[l]=='('&&s[r]=='?') x=dp[l][r-1]+dp[l+1][r-1]+p;
if(s[l]=='?'&&s[r]=='?') x=dp[l][r-1]+dp[l+1][r]+p;
x%=mod;
}
cout<<dp[1][n]<<endl;
}
本文深入解析了算法竞赛中两种常见问题的解决方案,包括构造贪心策略解决数字序列构造问题,以及使用区间动态规划解决括号序列深度求和问题,提供了详细的代码实现与复杂度分析。
598

被折叠的 条评论
为什么被折叠?



