Codeforces Round 965 (Div. 2)

news2024/9/22 7:24:24

前言

        有人在过七夕,我在打 cf ,还有某人独自一人在学校机房,凌晨一点骑上共享单车回宿舍欣赏沿途的秋风扫落叶。

        Standings:2166

        题目链接:Dashboard - Codeforces Round 965 (Div. 2) - Codeforces

A. Find K Distinct Points with Fixed Center

        题意:

        给一个点(x,y),要求构造 k 个点使得这 k 个点的中心是(x,y)。

        思路:

        分奇偶讨论,两两对应即可。

#include<cstdio>
#include<cstring>
using namespace std;

int T,x,y,k;

int main()
{
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d%d%d",&x,&y,&k);
		if(k & 1)
		{
			printf("%d %d\n",x,y);
			for (int i = 1;i <= k / 2;++ i) printf("%d %d\n%d %d\n",x + i,y + i,x - i,y - i);
		}
		else
		{
			for (int i = 1;i <= k / 2;++ i) printf("%d %d\n%d %d\n",x + i,y + i,x - i,y - i);
		}
	}
	return 0;
}

B. Minimize Equal Sum Subarrays

        题意:

        给你一个 1 ~ n 的排列 p ,你需要构造出一个新的 1 ~ n 的排列 q ,使得满足条件的 (i , j)对的数目最小:

        p_i+p_{i+1}+...+p_j=q_i+q_{i+1}+...+q_j

        思路:

        只要使每一位的前缀和不一样即可,其实整体往右挪一位就是答案。

        比赛时打得太丑,才知道 vector 的 erase 复杂度是 O(n)的,过 B 的时候就已经心态崩了

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

#define N 200005

int T,n,fst;
long long sum[N],a[N],b[N],pre[N],las[N],now;

int main()
{
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d",&n),sum[0] = now = 0ll;
		for (int i = 1,x;i <= n;++ i)
			scanf("%lld",&a[i]),sum[i] = sum[i - 1] + a[i],b[i] = 0,pre[i] = i - 1,las[i] = i + 1;
		fst = 1;
		for (int i = 1;i <= n;++ i)
		{
			if(i == n || (now + a[fst] != sum[i]))
			{
				b[i] = a[fst];
				now += b[i];
				fst = las[a[fst]];
			}
			else
			{
				b[i] = a[las[fst]];
				now += b[i];
				las[fst] = las[las[fst]];
			}
		}
		for (int i = 1;i <= n;++ i) printf("%lld ",b[i]);
		printf("\n");
	}
	return 0;
}

C. Perform Operations to Maximize Score

        题意:

        给一个序列 a 和一个 01 串 b ,可以进行 k 次操作,每次操作可以让 b 中为 1 的某一位对应的 a 加上一,求 k 次操作之后以下值的最大值 :

        max_{i=1}^n(a_i + median(c_i))

        其中 c_i 表示序列 a 挖去 a_i 之后的序列,median 表示中位数。

        思路:

        可以分 b_i = 0 和 b_i = 1 讨论。

        1.  b_i = 1 的情况:显然让 k 次操作都加在 a_i 上最优,O(n)扫一遍即可。

        2.  b_i = 0 的情况:发现最大的那个 a_i 能得到最大的贡献,于是我们只用考虑挖去最大的 a_i 后的序列,让它的中位数尽可能大即可。我们可以二分中位数的值,再判断是否合法即可。

        好在是压线调出来了,以致于没有掉大分。。。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;

#define N 200005

int T,n,mid,m;
long long k,ans,mx1,mx2;

struct Node
{
	int val,b;
}a[N],c[N];

long long max(long long x,long long y) { return x > y ? x : y ; }

int cmp(Node x,Node y) { return x.val < y.val ; }

int check(int x)
{
	int tmp = m - mid + 1;
	int fl = m;
	for (int i = m; i ;-- i)
		if(c[i].val >= x) -- tmp,fl = i - 1;
		else break;
	if(tmp <= 0) return 1;
	int now = k;
	for (int i = fl; i ;-- i)
	{
		if(c[i].b) now -= x - c[i].val,-- tmp;
		if(now <= 0 || tmp <= 0) break;
	}
	if(now < 0) return 0;
	if(tmp <= 0) return 1;
	return 0;
}

int main()
{
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d%lld",&n,&k),ans = a[n + 1].val = 0ll;
		mid = n / 2;
		for (int i = 1;i <= n;++ i)
		{
			scanf("%lld",&a[i].val);
			if(a[i].val >= mx1) mx2 = mx1,mx1 = a[i].val;
		}
		for (int i = 1;i <= n;++ i) scanf("%d",&a[i].b);
		sort(a + 1,a + n + 1,cmp);
		int bz = 0;
		for (int i = 1;i <= n;++ i)
			if(a[i].b)
			{
				int tp;
				if(i <= mid) tp = a[mid + 1].val;
				else tp = a[mid].val;
				ans = max(ans,a[i].val + k + tp);
			}
			else
			{
				bz = i;
			}
		if(bz)
		{
			m = 0;
			for (int i = 1;i <= n;++ i)
				if(i != bz) c[++ m].b = a[i].b,c[m].val = a[i].val;
			ans = max(ans,a[bz].val + c[mid].val);
			int l = c[mid].val;
			int r = 1e9;
			while (l <= r)
			{
				int md = (l + r) >> 1;
				if(check(md)) l = md + 1,ans = max(ans,a[bz].val + md);
				else r = md - 1;
			}
		}
		printf("%lld\n",ans);
	}
	return 0;
}

D. Determine Winning Islands in Race

        题意:

        给 n 座岛屿,第 i 座和第 i + 1 座之间有一座桥(基础桥),除此之外还有若干座桥(附加桥),所有桥都是单向的且由标号小的岛屿指向标号大的岛屿。最初,Elsie 在 1 号岛屿,Bessie 在 s 号岛屿,他们都需要前往 n 号岛屿;Bessie 只能走基础桥,而 Elsie 可以走附加桥。

        由 Bessie 率先开始,每一轮这个人都可以走一条存在的桥,然后他原先所在的岛屿立刻坍塌,这意味着所有与原先岛屿相连的桥也同时坍塌;如果当前无路可走,则这个人终止在这个岛屿。

        两个人都采取最优策略,对于每个 s\in[1,n-1] ,判断 Bessie 能否到达 n 号岛屿。

        思路:

        假设有一座 u -> v 的桥,若 E 可以通过这段桥超过 B ,则必须要满足一下条件:

        1. u < s

        2. v - s > t (t 是 A 到达 v 所用的最快时间)

        即  s \in [u+1,v-t-1]

        用 BFS 求出 A 到每个点的最短时间,再用差分数组统计贡献即可。

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;

#define N 200005

int T,n,m,cnt,st[N],dis[N],vis[N],dif[N];

struct Edge
{
	int next,to;
}ed[N << 1];

queue<int> q;

void add(int u,int v)
{
	ed[++ cnt].next = st[u];
	ed[cnt].to = v;
	st[u] = cnt;
	return;
}

void bfs()
{
	while (!q.empty()) q.pop();	
	q.push(1),vis[1] = 1;
	while (!q.empty())
	{
		int x = q.front();
		q.pop(),vis[x] = 0;
		for (int i = st[x]; ~i ;i = ed[i].next)
		{
			int rec = ed[i].to;
			if(dis[x] + 1 < dis[rec])
			{
				dis[rec] = dis[x] + 1;
				if(!vis[rec]) q.push(rec),vis[rec] = 1;
			}
			int l = x + 1;
			int r = rec - (dis[x] + 1) - 1;
			if(l <= r) ++ dif[l],-- dif[r + 1];
		}
	}
	return;
}

int main()
{
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d%d",&n,&m),cnt = 0;
		for (int i = 1;i <= n;++ i) st[i] = -1,dis[i] = n + 1,vis[i] = dif[i] = 0;
		dis[1] = dif[0] = 0;
		for (int i = 1;i < n;++ i) add(i,i + 1);
		for (int i = 1,u,v;i <= m;++ i) scanf("%d%d",&u,&v),add(u,v);
		bfs();
		for (int i = 1;i < n;++ i) dif[i] += dif[i - 1],printf("%d",(dif[i]) ? 0 : 1);
		printf("\n");
	}
	return 0;
}

E1. Eliminating Balls With Merging (Easy Version)

        题意:

        给一行小球,每个小球上面都标有一个分值,小球可以通过向左右吃掉分值小于等于自己的球,并加上所吃小球的分值。问有多少个小球有可能成为最后剩下的那个小球。

        思路:

        Easy Version 我们可以利用贪心,按分值从大到小将球排序,从大球到小球进行处理。我们用单调栈记录一下每个小球左右两边第一个比它大的小球,分别记作 l 和 r 。容易发现,如果 l 或者 r 能成功留下,且当前小球可以吃掉它,那么当前小球一定可以成功留下,反之不行。

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<stack>
using namespace std;

#define N 200005

int T,n,k,l[N],r[N],f[N],mx,ans;
long long a[N],pre[N];

struct Node
{
	long long val,id;
}b[N];

stack<int> q;

int cmp(Node x,Node y) { return x.val > y.val ; }

long long max(long long x,long long y) { return x > y ? x : y ; }

int main()
{
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d%d",&n,&k),pre[0] = f[0] = f[n + 1] = mx = ans = 0;
		for (int i = 1;i <= n;++ i)
		{
			scanf("%lld",&a[i]);
			b[i].id = i,b[i].val = a[i],f[i] = 0,mx = max(mx,a[i]),pre[i] = pre[i - 1] + a[i];
		}
		for (int i = 1;i <= n;++ i) f[i] = (a[i] == mx);
		sort(b + 1,b + n + 1,cmp);
		while (!q.empty()) q.pop();
		q.push(0),a[0] = 1e9 + 1ll;
		for (int i = 1;i <= n;++ i)
		{
			while (!q.empty() && a[i] >= a[q.top()]) q.pop();
			l[i] = q.top();
			q.push(i);
		}
		while (!q.empty()) q.pop();
		q.push(n + 1),a[n + 1] = 1e9 + 1ll;
		for (int i = n; i ;-- i)
		{
			while (!q.empty() && a[i] >= a[q.top()]) q.pop();
			r[i] = q.top();
			q.push(i);
		}
		for (int i = 1;i <= n;++ i)
		{
			if(b[i].val == mx) continue;
			int now = b[i].id;
			long long sum = pre[r[now] - 1] - pre[l[now]];
			if(sum >= a[l[now]]) f[now] |= f[l[now]];
			if(sum >= a[r[now]]) f[now] |= f[r[now]];
		}
		for (int i = 1;i <= n;++ i) ans += f[i];
		printf("%d\n",ans);
	}
	return 0;
}

E2. Eliminating Balls With Merging (Hard Version)

        题意:

        Hard Version 唯一的区别就是给出一个 x ,对于所有 i\in[x,n] ,都要统计子序列 1 ~ i 的 Easy Version 的问题。

        思路:

        按 Easy Version 的做法肯定会超时,我们试试 “返璞归真” ,回归最原始易得的想法。

        对于某个球 i 要是想留下来,就一定要把 1 ~ i - 1 都吃掉,那么我们可以计算想要把 1 ~ i - 1 都吃掉,至少需要往右吃到的位置 minr 再根据已经把 1 ~ i - 1 都吃掉的情况下,至多往右吃到的位置 maxr 。那么球 i 对答案的贡献区间就是 [minr , maxr] ,用差分数组标记即可。

        对于求 minr 和 maxr 的过程,可以用 ST 表 + 二分 做,循环判断向左最多吃到哪,和向右最优吃到哪,如果吃不动就跳出。这样是不会超时的,因为每次吃到卡住的地方都说明那个位置的分值比你目前拥有的一段区间的分值之和要大,也就是说每一次扩散都会让你手上的值至少翻倍,因此这一过程的复杂度是 log(最大分值) 的。

#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;

#define N 200005

int T,n,p,lg[N],dif[N];
long long a[N],pre[N],f[N][22];

stack<long long> st;

long long max(long long x,long long y) { return x > y ? x : y ; }

void RMQ()
{
	for (int i = 1;i <= lg[n];++ i)
		for (int j = 1;j + (1 << i) - 1 <= n;++ j)
			f[j][i] = max(f[j][i - 1],f[j + (1 << (i - 1))][i - 1]);
	return;
}

int getMINR(int x)
{
	int tl,tr;
	tl = tr = x;
	while (tl > 1)
	{
		int ml = 1;
		int mr = tl - 1;
		int now = tl;
		long long sum = pre[tr] - pre[tl - 1];
		int mid,len;
		while (ml <= mr)
		{
			mid = (ml + mr) >> 1;
			len = tl - mid;
			long long mx = max(f[mid][lg[len]],f[tl - (1 << lg[len])][lg[len]]);
			if(sum >= mx) now = mid,mr = mid - 1;
			else ml = mid + 1;
		}
		if(tl > 1 && tl == now)
		{
			ml = tr + 1;
			mr = n;
			now = tr;
			sum = pre[tr] - pre[tl - 1];
			while (ml <= mr)
			{
				mid = (ml + mr) >> 1;
				len = mid - tr;
				long long mx = max(f[tr + 1][lg[len]],f[mid - (1 << lg[len]) + 1][lg[len]]);
				if(sum >= mx && sum + pre[mid] - pre[tr] >= a[tl - 1]) now = mid,mr = mid - 1;
				else if (sum >= mx) now = mid,ml = mid + 1;
				else mr = mid - 1;
			}
			if(now == tr)
			{
				tr = -1;
				break;
			}
			else tr = now;
		}
		else tl = now;
	}
	return tr;
}

int getMAXR(int x)
{
	while (x < n)
	{
		int ml = x + 1;
		int mr = n;
		int now = x;
		long long sum = pre[x];
		while (ml <= mr)
		{
			int mid = (ml + mr) >> 1;
			int len = mid - x;
			long long mx = max(f[x + 1][lg[len]],f[mid - (1 << lg[len]) + 1][lg[len]]);
			if(sum >= mx) now = mid,ml = mid + 1;
			else mr = mid - 1;
		}
		if(now == x) break;
		x = now;
	}
	return x;
}

int main()
{
	lg[1] = 0;
	for (int i = 2;i <= 200000;++ i) lg[i] = lg[i >> 1] + 1;
	scanf("%d",&T);
	while (T --)
	{
		scanf("%d%d",&n,&p),pre[0] = 0ll,a[0] = a[n + 1] = 1e9 + 1,dif[0] = 0;
		for (int i = 1;i <= n;++ i)
			scanf("%lld",&a[i]),f[i][0] = a[i],pre[i] = pre[i - 1] + a[i],dif[i] = 0;
		RMQ();
		for (int i = 1;i <= n;++ i)
		{
			int mnr = getMINR(i);
			if(mnr == -1) continue;
			int mxr = getMAXR(i);
			++ dif[mnr],-- dif[mxr + 1];
		}
		for (int i = 1;i <= n;++ i)
		{
			dif[i] += dif[i - 1];
			if(i >= p) printf("%d ",dif[i]);
		}
		printf("\n");
	}
	return 0;
}

总结

        感觉总是会卡在前三题,导致后面一些能做的大分题没时间写,看来得多练练 ABC 了。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

未来能源技术

未来能源技术正处于全球焦点的中心&#xff0c;旨在应对气候变化、资源枯竭和能源安全的挑战。未来能源技术的发展方向集中在可再生能源、能源储存技术、智能电网、核聚变以及新材料的应用等多个领域。 1. 可再生能源技术 1.1 太阳能技术 太阳能技术是未来能源发展的核心领域之…

精密Δ-Σ ADC的有效噪声带宽

1 简介 即使对最有经验的模拟设计工程师来说&#xff0c;理解ADC噪声也是一项挑战。Δ-Σ ADC具有量化噪声和热噪声&#xff0c;其变化取决于ADC的分辨率、参考电压和输出数据速率。在系统层面上&#xff0c;噪声分析因附加的信号链组件而变得更加复杂&#xff0c;这些组件中的…

NLP_情感分类_序列模型方案

文章目录 项目背景代码导包读取数据文本预处理举例查看分词器数据集调整进一步剖析&#xff1a;对应Step [{i1}/{len(train_loader)}] 里的train_loader进一步剖析&#xff1a;Step [{i1}/{len(train_loader)}] 里的train_loader&#xff0c;原始的train_df 计算数据集中最长文…

Java 并发(四)—— volatile 和 synchronized

一、volatile 关键字 1.概念 如果我们将一个变量使用 volatile 修饰&#xff0c;这就指示 编译器&#xff0c;这个变量是共享且不稳定的&#xff0c;每次使用它都到主存中进行读取。 2.作用 保证变量对所有线程的可见性。但不能保证数据的原子性。因此不能完全保证线程安全…

STP(生成树)的概述和工作原理

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:Linux运维老纪的首页…

PHPStorm 环境配置与应用详解

​ 大家好&#xff0c;我是程序员小羊&#xff01; 前言&#xff1a; PHPStorm 是 JetBrains 出品的一款专业 PHP 集成开发环境&#xff08;IDE&#xff09;&#xff0c;凭借其智能的代码补全、调试功能、深度框架支持和前端开发工具&#xff0c;为用户提供了丰富的功能和工具…

简单的敏感词提示功能

简单的敏感词提示功能 1. 需求 公司现在接到通知&#xff0c;部分接口的部分手动输入字段&#xff0c;需要新增敏感词报红提示&#xff0c;敏感词汇现在应该是7000多个左右&#xff0c;需要我们提供一个敏感词校验接口&#xff0c;如果前端输入敏感词&#xff0c;则前端提示出…

在Unreal Engine中使用C++创建基础角色并添加移动功能

目录 引言 步骤一&#xff1a;创建C类 步骤二&#xff1a;编写C代码 步骤三&#xff1a;设置输入绑定 步骤四&#xff1a;在UE编辑器中测试 结论 引言 Unreal Engine&#xff08;UE&#xff09;以其强大的功能和灵活性在游戏开发界广受好评。本文将指导你如何在UE中通过…

校园外卖平台小程序的设计

管理员账户功能包括&#xff1a;系统首页&#xff0c;个人中心&#xff0c;用户管理&#xff0c;商家管理&#xff0c;菜品信息管理&#xff0c;菜品分类管理&#xff0c;购买菜品管理&#xff0c;订单信息管理&#xff0c;系统管理 微信端账号功能包括&#xff1a;系统首页&a…

揭开ChatGPT进化之谜:人工智能如何变得更聪明

近年来&#xff0c;人工智能&#xff08;AI&#xff09;领域取得了显著进展&#xff0c;尤其是在自然语言处理&#xff08;NLP&#xff09;方面。OpenAI的GPT系列模型&#xff0c;如GPT-3和ChatGPT&#xff0c;代表了这一领域的前沿技术。本文将围绕ChatGPT提升的原因、发展趋势…

基于JSP的个性化影片推荐系统

你好呀&#xff0c;我是计算机学姐码农小野&#xff01;如果有相关需求&#xff0c;可以私信联系我。 开发语言&#xff1a;JSP 数据库&#xff1a;MySQL 技术&#xff1a;JSP技术 工具&#xff1a;MyEclipse、Tomcat、MySQL 系统展示 首页 管理员功能模块 用户功能模块 …

国外评论家称《黑神话》PC版有性能问题 还有卡顿现象

《黑神话&#xff1a;悟空》即将正式发售&#xff0c;人们对这款游戏的期待值相当高。所以许多粉丝在耐心等待第一批评测报道&#xff0c;然后再购买这款游戏。在8月16日媒体评测解禁之前&#xff0c;有一位国外评论家认为《黑神话&#xff1a;悟空》是一款好游戏&#xff0c;但…

Vue的监视属性watch、computed和watch之间的区别

目录 1. 监视属性2. 监视属性的简写3. computed和watch之间的区别 1. 监视属性 监听对象: 监视属性可以监听普通属性和计算属性调用时间: 当监听的属性发生改变时。handler被调用immediate: true: 是否初始化时让handler调用一下。此时oldVlue为undefineddeep: false: watch默…

美国洛杉矶大带宽服务器的运维与监控

美国洛杉矶的大带宽服务器因其优越的地理位置、高速的网络连接以及充足的带宽资源&#xff0c;在全球范围内享有很高的声誉。为了确保这些服务器的稳定运行和高效服务&#xff0c;运维与监控工作显得尤为重要。以下是一些关于美国洛杉矶大带宽服务器运维与监控方面的科普内容。…

CentOS7 配置 nginx 和 php 方案

配置方案 一、安装软件二、编写配置文件&#xff0c;连接PHP三、引用文件四、测试 鉴于网上教程错综复杂&#xff0c;写下一这篇文章 本教程只需要三步即可 一、安装软件 yum install -y nginx php php-fpm二、编写配置文件&#xff0c;连接PHP 一般情况下在安装完 nginx 后…

css实现太极图

<template><div><!-- 太极图 --><div class"all"><div class"left box"></div><div class"right box"></div><div class"black"><div class"inner_white"><…

16.3 简单神经网络的实现

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; 工&#x1f497;重&#x1f497;hao&#x1f497;&#xff1a;野老杂谈 ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题.…

java或者sh脚本实现 实现 mysql 数据库定时导出并导入(适合linux和windows)

定时导出指定数据库的指定表导出到指定数据库 一、Java实现 1、contronller Slf4j Controller public class BackupController {AutowiredBackupService backupService;// 备份 // ResponseBody // PostMapping("/backup/backupByfile")Scheduled(cron&quo…

CANopen 控制多台设备的支持能力与定制方案评估

1. CANopen 支持的设备数量 CAN 总线的物理限制&#xff1a;CANopen 基于 CAN 总线协议&#xff0c;其设备数量受到 CAN 总线物理层的限制。标准 CAN 总线通常支持最多 127 个节点&#xff0c;但实际应用中&#xff0c;考虑到总线负载、波特率、线缆长度、网络拓扑等因素&#…

(Java)集合框架

1.集合的简介 集合Collection&#xff0c;也是一个数据容器&#xff0c;类似于数组&#xff0c;但是和数组是不一样的。集合是一个可变的容器&#xff0c;可以随时向集合中添加元素&#xff0c;也可以随时从集合中删除元素。另外&#xff0c;集合还提供了若干个用来操作集合中…