ABC337 A-G

Toyota Programming Contest 2024#1(AtCoder Beginner Contest 337) - AtCoder

手速五题之后看FG,一看榜G过的比F多...两题都有思路然后先开写了F像是大模拟写了一堆bug,赛后对拍调bug调完疯狂re,发现是对数组双倍操作了但数组长度没开两倍...

G赛时就看了眼猜了个动态开点权值线段树+树上启发式合并觉得不好写就先写F了,赛后才想起来可以用dfn序处理子树问题+主席树+容斥...

好消息是就算开局A读假题wa一发之后还能手速上分w

A - Scoreboard

题意:

判断\sum Xi 和\sum Yi 谁大,x大输出Takahashi,y大输出Aoki,平局Draw

代码:

void solve()
{
	int n, x = 0, y = 0;
	scanf("%d", &n);
	for (int i = 1, a, b; i <= n; ++i)
	{
		scanf("%d%d", &a, &b);
		x += a, y += b;
	}
	if (x > y)printf("Takahashi\n");
	if (x < y)printf("Aoki\n");
	if (x == y)printf("Draw");
}

B - Extended ABC

题意:

给出一个字符串,问改字符串是否为若干个连续的A,若干连续B,若干连续C拼接而成(可以为0个)

代码:

char ch[N];
void solve()
{
	scanf("%s", ch + 1);
	for (int i = 1, c = 'A'; ch[i]; ++i)
	{
		while (c <= 'C' && ch[i] != c)++c;
		if (c > 'C')
		{
			printf("No\n");
			return;
		}
	}
	printf("Yes\n");
}

C - Lining Up 2

题意:

N个人排队,第i个人排在第Ai个人后面,若Ai=-1说明这个人是排头,求队伍

题解:

记录每个人后面是谁然后dfs即可(因为只有一条路径所以可以直接写循环)

int p[N];
void solve()
{
	int n;
	scanf("%d", &n);
	for (int i = 1, x; i <= n; ++i)
	{
		scanf("%d", &x);
		if (x == -1)x = 0;
		p[x] = i;
	}
	for (int i = 1, x = 0; i <= n; ++i)
		x = p[x], printf("%d ", x);
}

D - Cheating Gomoku Narabe

题意:

给出一个N*M的由'x', '.', 'o'构成的字符矩阵,你可以将任意个'.'变成'o',问最少进行多少次操作能使字符矩阵中存在某一行/列中存在连续K个'o',若不能输出-1

题解:

二维前缀和秒了,枚举所有可能的区间,先判断这个范围内'x'的数量为0,若为0则这个区间变成全'o'的代价为这个区间内'.'的数量

vector<vector<char>>mp;
vector<vector<int>>s[2];
int get_sum(int f, int ux, int uy, int vx, int vy)
{
	return s[f][vx][vy] - s[f][ux - 1][vy] - s[f][vx][uy - 1] + s[f][ux - 1][uy - 1];
}
void solve()
{
	int n, m, k;
	scanf("%d%d%d", &n, &m, &k);
	mp.resize(n + 1);
	s[0].resize(n + 1);
	s[1].resize(n + 1);
	s[0][0].resize(m + 1);
	s[1][0].resize(m + 1);
	for (int i = 1; i <= n; ++i)
	{
		mp[i].resize(m + 1);
		s[0][i].resize(m + 1);
		s[1][i].resize(m + 1);
		getchar();
		for (int j = 1; j <= m; ++j)
		{
			mp[i][j] = getchar();
			s[0][i][j] = s[0][i - 1][j] + s[0][i][j - 1] - s[0][i - 1][j - 1] + (mp[i][j] == 'x');
			s[1][i][j] = s[1][i - 1][j] + s[1][i][j - 1] - s[1][i - 1][j - 1] + (mp[i][j] == '.');
		}
	}
	int ans = INF;
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j + k - 1 <= m; ++j)
		{
			if (get_sum(0, i, j, i, j + k - 1) == 0)
				ans = min(ans, get_sum(1, i, j, i, j + k - 1));
		}
	}
	for (int j = 1; j <= m; ++j)
	{
		for (int i = 1; i + k - 1 <= n; ++i)
		{
			if (get_sum(0, i, j, i + k - 1, j) == 0)
				ans = min(ans, get_sum(1, i, j, i + k - 1, j));
		}
	}
	if (ans == INF)printf("-1\n");
	else printf("%d\n", ans);
}

E - Bad Juice

题意:

交互题。你有n瓶果汁,其中有一瓶果汁是坏果汁,喝了第二天会喷射,你想要在一天内知道到底哪瓶果汁不是好果汁,为此你找来m个朋友(需要最小化m),给第i个朋友试吃了ki份果汁,分别为Ai,1...Ai,ki,第二天每个朋友会向你汇报他窜没窜(0表示没窜, 1表示窜了),然后你需要判断是哪瓶不是好果汁。

题目会先给你一个n,之后你需要输出一行一个整数m,之后m行每行先输出一个ki,之后跟ki个整数表示给第i个朋友喂了哪些果汁,之后评测机将会返回一个01串表示每位朋友是否吃坏肚子,之后你需要输出一个整数表示是哪一瓶果汁坏了。

题解:

按二进制给每位朋友喂果汁,这样就只需要logn(向上取整)名朋友就能完成试毒,具体实现见代码

       第j位朋友
第     1  2  3
 i  1  0  0  0
瓶  2  1  0  0
果  3  0  1  0    0表示不喝1表示喝
汁  4  1  1  0 
    5  0  0  1
    6  1  0  1
vector<int>v[N];
void solve()
{
	int n;
	scanf("%d", &n);
	int m = 0, t = 1;
	while (t < n)++m, t <<= 1;
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < m; ++j)
			if (i >> j & 1)v[j].push_back(i + 1);
	}
	cout << m << endl;
	for (int i = 0; i < m; ++i)
	{
		printf("%d ", v[i].size());
		for (auto j : v[i])printf("%d ", j);
		cout << endl;
	}
	char ch[100];
	scanf("%s", ch);
	int ans = 0;
	for (int i = 0; ch[i]; ++i)
		if (ch[i] == '1')ans += 1 << i;
	cout << ans + 1 << endl;
}

F - Usual Color Ball Problems

题意:

给出N个球,颜色分别为Ci,有M个盒子,每个盒子最多可装K个球且仅能装同色球,你会从左往右依次尝试把球装到盒子里,若还有装了球且未装满的盒子则会优先把球装进装球且未装满的盒子里,若没有盒子能装下当前的球,则舍弃这个球。

你需要分别求出把0, 1, 2, ..., n - 1个最前面的球保持顺序放到最后面之后进行装球操作后装在盒子里的球的数量总数

题解:

仅提供我的做法,感觉挺屎的...讲也讲不太明白...

首先题目的n种情况肯定不是单独求的,需要对把第一个球丢到末尾连续操作n次并不断维护答案

经过思考我们可以发现在把头上的一个球放到末尾最多只会有一个盒子装的发生东西变化(第一个球占的盒子被最前面的没有盒子的球抢占),所以我们可以想办法维护一些东西使得我们能够判断是否会有变化。

首先我们需要用set维护每个没有装入盒子的点的下标以便找出第一个没有被装入盒子的球,这里如果维护每个球的下标的话应该会TLE,所以我们只维护每种颜色的第一个没有被装入盒子的球的下标。

设第一个没被装入的球的下标为t,第一个球的颜色为x,在把第一个球丢到末尾之后若在t前的颜色为x的球数量变为k的倍数,则说明此时x的一个盒子被c[t]抢走了(在此前t前面有cnt*k+1个x色球,占了cnt+1个盒子,此时去掉开头则被占用的盒子变为cnt个,刚好被c[t]抢占一个)。

对于求一段区间内x色球的数量,可以对每种颜色开个vector存所有这种颜色求的下标,然后二分即可求得。

大致思路是这样,具体做法见代码

const LL N = 4e5 + 10;
int c[N], f[N];//f[i]表示颜色为i的球的第一个没有被装入盒子的球的下标(为0表示不存在没被装入的球)
vector<int>v[N];//每种颜色的球的下标
deque<int>mp[N];//颜色i占据的盒子的每个盒子装球的个数
set<int>st;//每种颜色第一个没被装入的球的下标
void solve()
{
	int n, m, k, s = 0, ans = 0;
	scanf("%d%d%d", &n, &m, &k);
	for (int i = 1; i <= n; ++i)
	{
		scanf("%d", &c[i]);
		v[c[i]].push_back(i);
	}
	for (int i = n + 1; i <= 2 * n; ++i)//二倍数组处理把第一个丢到最后的操作
	{
		c[i] = c[i - n];
		v[c[i]].push_back(i);
	}
	for (int i = 1; i <= n; ++i)//初始化,求初始情况的ans
	{
		if (mp[c[i]].size() && mp[c[i]].back() < k)
			++mp[c[i]].back(), ++ans;
		else if (s < m)
			mp[c[i]].push_back(1), ++s, ++ans;
		else if (!f[c[i]])
			st.insert(i), f[c[i]] = i;
	}
	for (int i = 1; i <= n; ++i)
	{
		printf("%d\n", ans);
		if (st.empty())continue;//没有球被扔掉
		int x = c[i], t = *st.begin();//被丢到后面的颜色,候选颜色的位置
		int l = upper_bound(v[x].begin(), v[x].end(), i) - v[x].begin();
		int r = lower_bound(v[x].begin(), v[x].end(), t) - v[x].begin();
		int sum = r - l;//删去首位之后t之前的x的个数
		if (sum % k == 0)//候补的能上来
		{
			//删除最后一个装x的盒子
			ans -= mp[x].back();
			mp[x].pop_back();
			int cnt = mp[x].size() * k;
			if (!f[x])//将颜色x加入候选名单
			{
				//printf("*%d ", l + cnt);
				st.insert(v[x][l + cnt]);
				f[x] = v[x][l + cnt];
			}
			else //重新求x的第一个没被装入的位置
			{
				st.erase(f[x]);
				st.insert(v[x][l + cnt]);
				f[x] = v[x][l + cnt];
			}
			//将候选加入新盒子
			int tl = lower_bound(v[c[t]].begin(), v[c[t]].end(), t) - v[c[t]].begin();
			int tr = upper_bound(v[c[t]].begin(), v[c[t]].end(), i + n) - v[c[t]].begin();
			//printf("%d %d %d ", t, tl, tr);
			int tsum = tr - tl;
			//printf("%d ", tsum);
			if (tsum <= k)//c[t]不再有候选
			{
				ans += tsum;
				f[c[t]] = 0;
				st.erase(t);
				mp[c[t]].push_back(tsum);
			}
			else
			{
				ans += k;
				st.erase(t);
				st.insert(v[c[t]][tl + k]);
				f[c[t]] = v[c[t]][tl + k];
				mp[c[t]].push_back(k);
			}
		}
		else if(f[x])//重新求x的第一个没被装入的位置
		{
			int cnt = mp[x].size() * k;
			int p = upper_bound(v[x].begin(), v[x].end(), i) - v[x].begin();
			st.erase(v[x][p + cnt - 1]);
			st.insert(v[x][p + cnt]);
			f[x] = v[x][p + cnt];
		}
	}
}

G - Tree Inversion

题意:

题目给出一个n个节点的无根树,对每个点u求f(u):符合以下条件的点对(w,v)的数量:u到v的简单路径经过w。(w可以为u)

题解:

很容易想到换根DP,难点在于求以任意u为根时,其子节点w的子树中编号小于u的点v的数量。

这里可以通过dfn序把子树变成线性之后用主席树+容斥处理,具体做法见代码

从严鸽鸽那里改来的主席树板子数据结构学习笔记(7) 主席树 - 知乎 (zhihu.com),挺好用的,知道原理其实还挺好手搓的

const LL N = 2e5 + 10, M = N;
//主席树
#define ls(x) (tr[x].ls)
#define rs(x) (tr[x].rs)
#define s(x) tr[x].s
struct node
{
	int ls, rs, s;
}tr[32 * N];//logM * N
int root[N], tot;
void push_up(int i)
{
	s(i) = s(ls(i)) + s(rs(i));
}
void updata(int pos, int data, int l, int r, int last, int now)
{
	if (l == r)
	{
		s(now) = s(last) + data;
		return;
	}
	ls(now) = ls(last), rs(now) = rs(last);
	int mid = l + r - 1 >> 1;
	if (pos <= mid)
		updata(pos, data, l, mid, ls(last), ls(now) = ++tot);
	else
		updata(pos, data, mid + 1, r, rs(last), rs(now) = ++tot);
	push_up(now);
}
void updata(int pos, int data, int last, int now)
{
	updata(pos, data, -M, M, last, now);
}
int query_kth(int k, int l, int r, int last, int now)
{
	if (l == r)return l;
	int mid = l + r - 1 >> 1, dt = s(ls(now)) - s(ls(last));
	if (dt >= k)return query_kth(k, l, mid, ls(last), ls(now));
	return query_kth(k - dt, mid + 1, r, rs(last), rs(now));
}
//求区间第k大用的,这里没用上
int query_kth(int k, int last, int now)
{
	return query_kth(k, -M, M, last, now);
}
int query_range(int ql, int qr, int l, int r, int last, int now)
{
	if (ql <= l && r <= qr)return s(now) - s(last);
	int mid = l + r - 1 >> 1, res = 0;
	if (ql <= mid)res += query_range(ql, qr, l, mid, ls(last), ls(now));
	if (qr > mid)res += query_range(ql, qr, mid + 1, r, rs(last), rs(now));
	return res;
}
//求数组在下标last+1到now之间,大小在ql到qr之间的数的数量
int query_range(int ql, int qr, int last, int now)
{
	return query_range(ql, qr, -M, M, last, now);
}
//
int dfn[N], ed[N], idx;
vector<int>e[N];
LL dp[N];
void build(int u, int f)//处理dfn序
{
	dfn[u] = ++idx;
	root[idx] = ++tot;
	updata(u, 1, root[idx - 1], root[idx]);
	for (auto v : e[u])if (v != f)
		build(v, u);
	ed[u] = idx;
}
void dfs0(int u, int f)//预处理f(1)
{
	for (auto v : e[u])if (v != f)
	{
		dfs0(v, u);
		dp[u] += dp[v] + query_range(1, v - 1, root[dfn[v] - 1], root[ed[v]]);
	}
}
void dfs(int u, int f)//换根dp
{
	for (auto v : e[u])if (v != f)
	{
		dp[v] = dp[u] - query_range(1, v - 1, root[dfn[v] - 1], root[ed[v]]);
		dp[v] += u - 1 - query_range(1, u - 1, root[dfn[v] - 1], root[ed[v]]);
		dfs(v, u);
	}
}
void solve()
{
	int n;
	scanf("%d", &n);
	for (int i = 1; i < n; ++i)
	{
		int u, v;
		scanf("%d%d", &u, &v);
		e[u].push_back(v);
		e[v].push_back(u);
	}
	build(1, 0);
	dfs0(1, 0);
	dfs(1, 0);
	for (int i = 1; i <= n; ++i)
		printf("%lld ", dp[i] + i - 1);
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/337196.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Django开发_14_后台管理及分页器

一、后台管理 &#xff08;一&#xff09;登录 http://127.0.0.1:8000/admin/ &#xff08;二&#xff09;创建超级用户 manage.py createsuperuser &#xff08;三&#xff09;注册模型 admin.py&#xff1a; models [model1&#xff0c;model2&#xff0c;model3 ]ad…

VScode新增设备实现无感接入(不需要输入密码)

VScode远程开发接入设备&#xff0c;默认是需要输入密码的&#xff0c;但是日常开发中刷新就需要重新输入密码&#xff0c;很烦人。配置ssh的RSA密钥后会&#xff0c;就可以直接系统级别验证接入&#xff0c;对开发人员来说验证步骤就透明了&#xff0c;实现无感接入&#xff0…

Object.prototype.toString.call个人理解

文章目录 这段代码的常见用处参考文献&#xff1a; 拆分理解1、Object.prototype.toString小问题参考文献&#xff1a; 2、call函数的作用参考文献 3、继续深入一些&#xff08;这部分内容是个人理解&#xff0c;没有明确文献支撑&#xff09; 这段代码的常见用处 Object.prot…

力扣645.错误的集合

一点一点地刷&#xff0c;慢慢攻克力扣&#xff01;&#xff01; 王子公主请看题 集合 s 包含从 1 到 n 的整数。不幸的是&#xff0c;因为数据错误&#xff0c;导致集合里面某一个数字复制了成了集合里面的另外一个数字的值&#xff0c;导致集合 丢失了一个数字 并且 有一个数…

el-upload中的before-upload不生效

我们先来看看官方对before-upload的定义 before-upload是在上传文件时触发&#xff0c;不是添加文件时触发&#xff0c;添加文件时触发 on-change。 所以如果我们要在添加文件时&#xff0c;对文件的大小和后缀等等进行判断&#xff0c;可以用 on-change 方法来实现。 checkSu…

​WordPress顶部管理工具栏怎么添加一二级自定义菜单?

默认情况下&#xff0c;WordPress前端和后台页面顶部都有一个“管理工具栏”&#xff0c;左侧一般就是站点名称、评论、新建&#xff0c;右侧就是您好&#xff0c;用户名称和头像。那么我们是否可以在这个管理工具栏中添加一些一二级自定义菜单呢&#xff1f; 其实&#xff0c…

史上最全EasyExcel

一、EasyExcel介绍 1、数据导入&#xff1a;减轻录入工作量 2、数据导出&#xff1a;统计信息归档 3、数据传输&#xff1a;异构系统之间数据传输 二、EasyExcel特点 Java领域解析、生成Excel比较有名的框架有Apache poi、jxl等。但他们都存在一个严重的问题就是非常的耗内…

64位ATT汇编语言as汇编ld链接,执行报错Segmentation fault

absCallAndPrintAbsAsLd.s里边的内容如下&#xff1a; .section .datastringToShow:.ascii "The abs of number is %d\n\0" .global _start .section .text _start:pushq %rbpmovq %rsp,%rbpmovq $-5,%rdicall absmovq $stringToShow,%rdimovq %rax,%rsicall printf…

EasyRecovery2024电脑数据恢复工具好不好用?

Ontrack是我们综述中的第一个产品&#xff0c;由于该软件的功效和广度&#xff0c;我认为它完全基于业务。有一个具有基本功能的免费版本和一系列付费版本&#xff0c;不仅可以恢复文件&#xff08;免费版和家庭版&#xff09;&#xff0c;还可以创建磁盘映像/从 CD 和 DVD 恢复…

集美大学“第15届蓝桥杯大赛(软件类)“校内选拔赛 H卯酉东海道

dijk spfa思想 然后你需要存一下每个点 * l种颜色&#xff0c;你开个数组存一下 st[i][j] 为到达i点且到达以后是j颜色的最小距离是否已经确定了 #include<bits/stdc.h> using namespace std; using ll long long; const int N 3e510; struct Edge{ll to,col,w;bool …

竞赛保研 机器视觉opencv答题卡识别系统

0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 答题卡识别系统 - opencv python 图像识别 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非常推荐&#xff01; &#x1f947;学长这里给一个题目综合评分(每项满分5分…

Chatopera 云服务支持大语言模型对话(LLM),定制您的聊天机器人

2024 年&#xff0c;Chatopera 云服务继续不断完善&#xff0c;为开发者提供最好的定制聊天机器人的工具。在过去的一年&#xff0c;用户们反映最多的建议是 Chatopera 云服务内置大语言模型的对话&#xff0c;今天 Chatopera 云服务完成了产品升级&#xff0c;满足了这个诉求。…

Python-setup打包命令

一、setup.py文件的书写 这个资料有很多&#xff0c;不多赘述&#xff0c;setup 函数常用的参数如下&#xff1a; 基础描述信息&#xff1a; name 包名称&#xff08;起一个响亮的名字&#xff09;version (-V) 包版本author 程序的作者author_email 程序的作者的邮箱地址mai…

Datawhale 强化学习笔记(三)基于策略梯度(policy-based)的算法

文章目录 参考基于价值函数的缺点策略梯度算法REINFORCE 算法策略梯度推导进阶策略函数的设计离散动作的策略函数连续动作的策略函数 参考 第九章 策略梯度 之前介绍的 DQN 算法属于基于价值(value-based)的算法&#xff0c;基于策略梯度的算法直接对策略本身进行优化。 将策…

Cortex-M3/M4内核中断及HAL库函数详解(1):中断相关寄存器

0 工具准备 Keil uVision5 Cortex M3权威指南&#xff08;中文&#xff09; Cortex M3与M4权威指南 stm32f407的HAL库工程 STM32F4xx中文参考手册 1 NVIC相关寄存器介绍 在Cortex-M3/M4内核上搭载了一个异常响应系统&#xff0c;支持为数众多的系统异常和外部中断。其中&#…

[AutoSar]BSW_OS 07 Autosar OS_时间保护

一、 目录 一、关键词平台说明一 时间保护的概念 关键词 嵌入式、C语言、autosar、OS、BSW 平台说明 项目ValueOSautosar OSautosar厂商vector &#xff0c;芯片厂商TI 英飞凌编程语言C&#xff0c;C编译器HighTec (GCC) >>>>>回到总目录<<<<<…

【设计模式】什么是外观模式并给出例子!

什么是外观模式&#xff1f; 外观模式是一种结构型设计模式&#xff0c;主要用于为复杂系统、库或框架提供一种简化的接口。这种模式通过定义一个包含单个方法的高级接口&#xff0c;来隐藏系统的复杂性&#xff0c;使得对外的API变得简洁并易于使用。 为什么要使用外观模式&a…

详解IPV6地址

华子目录 IPV6IPV4和IPV6的报头IPV6的地址组成IPV6地址写法IPV6地址分类单播地址多播地址IPV6下的组播MAC地址 协议ICMPV61.PMTU2.NDP3.前缀通告auto-config 配置静态RIPNGOSPFV3BGP4 解决IPV4和IPV6兼容问题 (共存问题)普通tunnel6to4 tunnel双栈 IPV6 特征&#xff08;升级点…

Lattice Diamond软件下载

Lattice Diamond软件官方下载方法 对于电子设计中的很多开发软件&#xff0c;下载渠道有很多&#xff0c;但是安装包的下载&#xff0c;任何时候在官网上都可以可靠的找到资源并进行下载&#xff0c;因此这里对Diamond软件的下载&#xff0c;介绍官网的下载方法。 1 Lattice官…

渣土车识别摄像机

渣土车识别摄像机是一种应用于城市管理和交通监控领域的先进技术设备。它通过摄像头实时捕捉道路上行驶的车辆画面&#xff0c;并利用先进的图像识别和算法分析技术对渣土车进行准确识别。渣土车识别摄像机的设计需要兼顾高清晰度、高速度、大容量等特点&#xff0c;以满足实际…