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则无解。
复杂度: 。
#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,其中每一个’?‘均可被替换为’(’、’)’,求所有可能的全部’?'被替换后形成的字符串的括号嵌套深度之和,替换后形成的字符串不一定是合法的括号序列 。
解法:
考虑区间DP,设 为串 替换后形成的所有串的括号嵌套深度之和。现求 的值,对 、 进行讨论,有如下的转移方程:
- 若 ,则 一定不对答案产生贡献: ;
- 若 ,同理有: ;
- 若 且 ,我们已知 ,仅需考虑 、 两端对答案的贡献。设 ,k为T中’?‘的数量,则当T中所有的’?'被替换后将形成 种不同的串,故 、 的贡献为 : ;
- 若 且 , 能被替换为’(‘或’)’,故产生两种新串。当 时,整个串对答案的贡献同1. ,为 ;当 时,整个串对答案的贡献同3. ,为 。因此有: ;
- 若 且 ,分析同上有: ;
- 若 且 ,产生四种新串。当 时, 和 两种串产生的贡献之和为 ;同理,当 时, 和 两种串产生的贡献之和为 。根据上述讨论我们将 且 的情况计算了两次,但没计算 且 的情况。再由3. 的分析,我们得到当 且 时的贡献为 ,而 其实就是当 且 时的贡献。综上有: 。
复杂度: 。
#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;
}