2025.3.14 总结
T1
50 pts。
直接暴力。
思路
我们可以发现,题目中的变化只是将字符串中的 A 挪到了最后,所以如果出现了 AABC 这种情况,才会发生连锁反应,因为是从后往前反应,所以枚举的时候从前往后,统计 A 的个数,如果遇到了 B,并且下一个是 C,答案就加上 A 的个数,如果是 C 的话,就将个数清零。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
string s;
signed main()
{
cin.tie(0)->sync_with_stdio(false);
cin>>s;
int ans=0,cnt=0;
for(int i=0;i<s.size();++i)
{
if(s[i]=='A') ++cnt;
else if(s[i]=='B')
{
if(i+1<s.size()&&s[i+1]=='C')
{
ans+=cnt;
++i;
}
else cnt=0;
}
else cnt=0;
}
cout<<ans;
return 0;
}
T2
50 pts。
最短路暴力。
思路
记忆化搜索乘法的情况即可。
代码
#include<bits/stdc++.h>
#define int unsigned long long
using namespace std;
int n,a,b,c,d;
unordered_map<int,int> dp;
int dfs(int x)
{
if(dp.count(x)) return dp[x];
int mn=x*d;
if(x%2==0) mn=min(mn,dfs(x/2)+a);
else mn=min(mn,min(dfs((x-x%2)/2)+(x%2)*d,dfs((x+2-x%2)/2)+(2-x%2)*d)+a);
if(x%3==0) mn=min(mn,dfs(x/3)+b);
else mn=min(mn,min(dfs((x-x%3)/3)+(x%3)*d,dfs((x+3-x%3)/3)+(3-x%3)*d)+b);
if(x%5==0) mn=min(mn,dfs(x/5)+c);
else mn=min(mn,min(dfs((x-x%5)/5)+(x%5)*d,dfs((x+5-x%5)/5)+(5-x%5)*d)+c);
return dp[x]=mn;
}
void solve()
{
dp.clear();
cin>>n>>a>>b>>c>>d;
dp[0]=0,dp[1]=d;
cout<<dfs(n)<<'\n';
return;
}
signed main()
{
cin.tie(0)->sync_with_stdio(false);
int t;
cin>>t;
while(t--) solve();
return 0;
}
T3
50 pts。
LCA 暴力。
思路
直接用并查集维护。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+5;
string s;
int n,fa[N],cnt[N],ans;
vector<int> g[N];
int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}
void mark(int u)
{
vector<int> ve;
int sum=0;
for(int v:g[u])
{
if(s[v]=='R')
{
int y=find(v);
ve.emplace_back(cnt[y]);
sum+=cnt[y],ans+=cnt[y];
}
}
int s=0;
for(int i:ve) s+=i*(sum-i);
ans+=s/2;
return;
}
signed main()
{
cin.tie(0)->sync_with_stdio(false);
cin>>n>>s;
s=' '+s;
for(int i=1;i<=n;++i) fa[i]=i,cnt[i]=1;
for(int i=1,x,y;i<n;++i)
{
cin>>x>>y;
if(s[x]=='R'&&s[y]=='R')
{
int u=find(x),v=find(y);
if(u!=v)
{
fa[u]=v;
cnt[v]+=cnt[u];
}
}
g[x].emplace_back(y),g[y].emplace_back(x);
}
for(int i=1;i<=n;++i)
{
if(s[i]=='B')
{
mark(i);
}
}
cout<<ans;
return 0;
}
T4
0 pts。
思路
只有出现了零的时候,这一位才会是零,所以可以使用树状数组统计每一位的答案,每次更新的时候就更新这个数的每一位即可。
代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e5+5,mod=1e9+7;
int n,a[N],pw[N];
struct Node{
int tr[N];
void update(int idx,int val)
{
while(idx<=n)
{
tr[idx]+=val;
idx+=idx&-idx;
}
return;
}
int query(int idx)
{
int sum=0;
while(idx)
{
sum+=tr[idx];
idx-=idx&-idx;
}
return sum;
}
}tree[35];
signed main()
{
cin.tie(0)->sync_with_stdio(false);
cin>>n;
for(int i=1;i<=n;++i) cin>>a[i];
pw[0]=1;
for(int i=1;i<N;++i) pw[i]=(pw[i-1]*2)%mod;
for(int i=1;i<=n;++i)
{
for(int j=0;j<=35;++j)
{
if((a[i]>>j)&1) tree[j].update(i,1);
}
}
int q;
cin>>q;
for(int op,l,r;q--;)
{
cin>>op>>l>>r;
if(op==1)
{
for(int j=0;j<=30;++j)
{
if((a[l]>>j)&1) tree[j].update(l,-1);
}
a[l]=r;
for(int j=0;j<=30;++j)
{
if((a[l]>>j)&1) tree[j].update(l,1);
}
}
else
{
int sum=0;
for(int j=0;j<=30;++j)
{
sum=(sum+(pw[tree[j].query(r)-tree[j].query(l-1)]-1)*pw[j]%mod)%mod;
}
cout<<sum<<'\n';
}
}
return 0;
}

浙公网安备 33010602011771号