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;
}
posted @ 2025-03-16 14:43  BUMIE  阅读(27)  评论(0)    收藏  举报