蓝桥杯2023C++A组

(此文为简单的赛后记录,代码没有经过修改不保证正确

A 幸运数

将数字分为前一半和后一半dp方案数再乘起来

B 有奖问答

dpi,j表示第i轮 得分为10j的情况
注意一下在任意轮都可以结束并且j=10是不能转移的

C 平方差

当且仅当 x=4a(2b+1)(a,b>=0) 统计

时间复杂度:O(logR)

D 更小的数

一个重要的观察:子串反转要么在首位和末尾比出大小,要么首位和末尾相等

做法一:dpi,j 表示反转 j 到 j + i - 1 的子串是否更小 O(n2)

做法而:分治,将左(右)区间每个位置看成一个二维的点(x,y),x是当前位置是什么数字,y是当前位置之前(之后)是什么数字,枚举右区间,对左区间统计二维前缀和就可以统计跨越左右区间贡献的答案

时间复杂度:O(nD2logn) D 是字符集大小,|D|=10

E 颜色平衡树

不会wuwu

F 买瓜

天天看华强结果一点思路都没有,,,

G 网络稳定性

说法很多

求最大生成树

之后就是一个求最小边的问题

考场写了倍增

O(Nlog M+(Q+N)log N)

#include<cstdio>
#include<iostream>
#include<vector>
#include<algorithm>
#define inf 1e7

using namespace std;

const int N = 200010, M = 300010;

int n,m,q,f[N][19],g[N][19],dep[N],fa[N],o,hd[N],vis[N];

struct edge{int u,v,w;}e[M];
struct Edge{int v,nt,w;}E[N<<1];

bool cmp(const edge&A,const edge&B){return A.w>B.w;}

void adde(int u,int v,int w){
	E[o]=(Edge){v,hd[u],w};hd[u]=o++;
	E[o]=(Edge){u,hd[v],w};hd[v]=o++;
}

int find(int x){return fa[x]==x?x:fa[x]=find(fa[x]);}

void dfs(int u,int F){
	vis[u]=1;
	for(int i=1;(1<<i)<=dep[u];++i){
		f[u][i] = f[f[u][i-1]][i-1];
		g[u][i] = min(g[f[u][i-1]][i-1] , g[u][i-1]); //!
	}
	for(int i=hd[u];~i;i=E[i].nt){
		int v=E[i].v, w=E[i].w;
		if(v==F)continue;
		dep[v] = dep[u] + 1;
		f[v][0] = u;
		g[v][0] = w;
		dfs(v,u);
	}
}

int solve(int u,int v){
	int re=inf;
	if(dep[u]<dep[v])swap(u,v);
	int du=dep[u]-dep[v];
	for(int i=18;~i;--i)if((du>>i)&1)re=min(re,g[u][i]),u=f[u][i];
	if(u==v)return re;
	for(int i=18;~i;--i){
		if(f[u][i]!=f[v][i]){
			re = min(re, g[u][i]);
			re = min(re, g[v][i]);
			u = f[u][i], v=f[v][i];
		}
	}
	re = min(re, g[u][0]);
	re = min(re, g[v][0]);
	return re;
}

int main(){
	scanf("%d%d%d",&n,&m,&q);
	for(int i=1;i<=m;++i){
		scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
	}
	//生成树 
	sort(e+1,e+m+1,cmp);
	for(int i=1;i<=n;++i)fa[i]=i,hd[i]=-1;
	for(int i=1;i<=m;++i){
		int fx = find(e[i].u);
		int fy = find(e[i].v);
		if(fx == fy)continue;
		fa[fy]=fx;
		adde(e[i].u,e[i].v,e[i].w);
	}
	//倍增求答案 
	for(int i=1;i<=n;++i)if(!vis[i])dfs(i,0);
	for(int i=1;i<=q;++i){
		int u,v;
		scanf("%d%d",&u,&v);
		if(find(u)!=find(v)){puts("-1");continue;}
		cout<<solve(u,v)<<endl;
	}
	return 0;
}

H 异或和之和

按位统计答案,统计异为0 和 1的前缀个数相乘即可

I 像素放置

我想写插头dp
没有写出来,最后二十分钟来调暴力也没调出来,很可惜50%
吸取教训:像这种题肯定是先写暴力的,就算要写正解也需要暴力来对拍

O(NM4M) 不知道能不能过。。。等题解

J 翻转硬币

不会做orz

posted @   tkys_AUSTIN  阅读(183)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示