ABC359D&E&G 题解
ABC359D Avoid K Palindrome#
题目大意#
给定一个长度为 的字符串 ,由 A
,B
或 ?
组成。可以在 ?
处任意填 A
或 B
。再给定一个常数 ,问有多少种填法可以使 的每一个长度为 的子串都不是回文串,即成为一个好串。
Solve#
注意到 ,考虑暴力 或状压 。由于状态转移比较直观,这里用状压。
令 表示 的前 位是好串,以 结尾的长度为 的子串状态为 的方案数。 二进制下的第 位为 表示 对应的这一位是 A
,否则是 B
。
对于遍历到的 ,枚举第 位的状态 ,进行状态转移。
- 若 为
A
或?
,则第 位的状态 为 删去最左侧的一位,左移一位,再将对应 的最右侧的一位变为 ,二进制表示为now<<1&(1<<k)-1|1
。 - 若 为
B
或?
,则第 位的状态 为 删去最左侧的一位,左移一位,二进制表示为now<<1&(1<<k)-1
。
若 不是回文,则令 加上 。
Code#
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
short f=1;
int x=0;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
#define mod 998244353
int n,m,dp[1010][1024]={1},res,ans,k;
char s[1010];
bool f[1024];//预处理出哪些状态不是回文串
signed main()
{
n=read();m=1<<(k=read());
scanf("%s",s+1);
for(int now=0;now<m;now=-~now)
{
f[now]=0;
for(int i=0;i<(k>>1);i=-~i)
if((now>>i&1)^(now>>(k-1-i)&1))
{
f[now]=1;
break;
}
}
for(int i=1;i<=n;i=-~i)
for(int now=0;now<m;now=-~now)
{
int nxt=now<<1&m-1;
if(s[i]=='A'||s[i]=='?')
if(i<k||f[nxt|1])//i<k时特判
dp[i][nxt|1]=(dp[i][nxt|1]+dp[i-1][now])%mod;//注意取模
if(s[i]=='B'||s[i]=='?')
if(i<k||f[nxt])
dp[i][nxt]=(dp[i][nxt]+dp[i-1][now])%mod;
}
for(int now=0;now<m;now=-~now)
ans=(ans+dp[n][now])%mod;
return printf("%lld",ans),0;
}
ABC359E Water Tank#
题目大意#
给定一个长度为 的序列 ,和一个长度为 初始为 的序列 。每一轮在 上进行如下操作:
- 将 的值增加 。
- 依次遍历 ,若 且 ,则将 减 ,将 加 。
求对于 ,需要多少轮操作能使 。
Solve#
如果要使 ,首先要将 填满,耗费 ,再向 填 。
如果要使 ,要将 左侧的都填满,共耗费 。
如果要使 ,要将 左侧的都填满,共耗费 。
以此类推,若 是前缀最大值,那么就要耗费 的代价把 左侧全填满,也就是填成一个矩形。
那如果 不是前缀最大值呢?以 为例。
忽略墙的厚度,则相当于把 和 间填成一个矩形,共耗费 。
以此类推,若 不是前缀最大值,那么需要去找 左侧第一个比它高的 ,花费即为 。
单调栈实现之。
Code#
// LUOGU_RID: 163040327
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
short f=1;
int x=0;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,h[200010],sum[200010];
stack<int>s;
signed main()
{
n=read();
for(int i=1;i<=n;i=-~i)
{
h[i]=read();
while(!s.empty()&&h[s.top()]<=h[i]) s.pop();
if(s.empty()) sum[i]=i*h[i];
else sum[i]=sum[s.top()]+(i-s.top())*h[i];
printf("%lld ",sum[i]+1);
s.push(i);
}
return 0;
}
ABC359G Sum of Tree Distance#
题目大意#
给定一棵 个节点树,和每个点的权值 。求 。
Solve#
点分治板子啊。
对于分治出的以 为根的子树,令 为 。 是子树中每个点的深度,也就是到根节点的距离。
用 统计所有点权为 的点到子树的根的距离之和,再用 统计所有点权为 的点的个数,当遍历到点 时,让答案加上 ,也就是加上之前遍历过的点到 点的距离和。然后在遍历完这一分支之后修改 和 数组以实现容斥即可,没啥细节。
Code#
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline int read()
{
short f=1;
int x=0;
char c=getchar();
while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
while(c>='0'&&c<='9') x=(x<<1)+(x<<3)+(c^48),c=getchar();
return x*f;
}
int n,v[200010],ans;
vector<int>e[200010];
int mn,root,siz[200010];
int dep[200010],sum[200010],now,cnt[200010];
bool vis[200010];
vector<int>a,b;
void get_siz(int u,int fa)
{
siz[u]=1;
int mx=0;
for(auto i:e[u])
if(i!=fa&&!vis[i])
get_siz(i,u),
mx=max(mx,siz[i]),siz[u]+=siz[i];
mx=max(mx,now-siz[u]);
if(mx<mn) mn=mx,root=u;
}
inline int get_rt(int u)/*找重心*/
{
mn=n;now=siz[u];
get_siz(u,0);
return root;
}
void get_dis(int u,int fa)
{
a.push_back(u);
for(auto i:e[u])
if(i!=fa&&!vis[i])
dep[i]=-~dep[u],
get_dis(i,u);
}
inline void calc(int u)
{
dep[u]=1;
a.clear();
get_dis(u,0);
for(auto i:a)
ans+=sum[v[i]]+dep[i]*cnt[v[i]];
}
void solve(int u)
{
vis[u]=1;
cnt[v[u]]=-~cnt[v[u]];/*别忘了算上子树的根*/
for(auto i:e[u])
if(!vis[i])
{
calc(i);
for(auto i:a)
sum[v[i]]+=dep[i],cnt[v[i]]=-~cnt[v[i]],
b.push_back(i);
}
for(auto i:b) sum[v[i]]-=dep[i],cnt[v[i]]--;
b.clear();cnt[v[u]]--;
for(auto i:e[u])
if(!vis[i]) solve(get_rt(i));
}
signed main()
{
siz[1]=n=read();
for(int i=1,a,b;i<n;i=-~i)
a=read(),b=read(),
e[a].push_back(b),e[b].push_back(a);
for(int i=1;i<=n;i=-~i) v[i]=read();
solve(get_rt(1));
return printf("%lld",ans),0;
}
(点分治的写法可能有些丑,凑合着看吧。)
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】