栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

[Acwing] 第 19 场周赛

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

[Acwing] 第 19 场周赛

前言

传送门 :

3992. 树上有猴

t a g : tag : tag: 合法问题 有效区间 数学分析
题意 :
给定一个 a [ ] a[] a[],对于 a [ i ] a[i] a[i]表示使得当前的 c n t + a [ i ] cnt+a[i] cnt+a[i],询问有多少个合法的 c n t cnt cnt
其中各个期间的 c n t cnt cnt需要满足 m ≥ c n t ≥ 0 m ge cnt ge 0 m≥cnt≥0

思路 :
首先因为每个状态都是独立的,因此我们可用对 a [ i ] a[i] a[i]求前缀和 s [ i ] s[i] s[i],表示当前这个时间段和初始相差的数量

则我们可用设一开始的数量为 x x x

0 ≤ x ≤ w 0 ≤ x + s 1 ≤ w 0 ≤ x + s 2 ≤ w . . . . . begin{aligned} & 0 le x le w\ & 0 le x+s_1 le w\ & 0 le x+s_2 le w\ &..... end{aligned} ​0≤x≤w0≤x+s1​≤w0≤x+s2​≤w.....​

化简式子我们我们可用得

0 ≤ x ≤ w − s 1 ≤ x ≤ w − s 2 ≤ x + ≤ w . . . . . begin{aligned} & 0 le x le w\ & -s_1 le x le w\ & -s_2 le x+ le w\ &..... end{aligned} ​0≤x≤w−s1​≤x≤w−s2​≤x+≤w.....​

因此我们只需要找到所有区间的交集即可,即使得左边最大右边最小

Code :

int a[N],sum[N];

int n,m;


void solve(){
	cin>>n>>m;
	for(int i=1;i<=n;i++)  cin>>a[i],sum[i] = sum[i-1] + a[i];
	
	
	int maxn = m ;
	int minn = 0;
	
	for(int i=1;i<=n;i++){
		maxn = min(maxn, m - sum[i]);
		minn = max(minn, -sum[i]);
	}
	
	cout< 
3993. 石子游戏 

t a g : tag: tag:值域 枚举 前缀和优化
题意 :
给定一个数组 a [ ] a[] a[],询问最小的操作次数使得所有元素相同

操作定义如下 :

  1. 每次选取一个 h h h为上限
  2. 将所有 a [ i ] > k a[i]>k a[i]>k的部分全部取出

每次操作取出的总和不得超过 k k k

思路 :
首先一个非常暴力的解法是

每次从大往小的取 h h h,尽可能的取 h h h使得 s u m sum sum每次减小的最大

但是如何判断这个 h h h呢 ? n 2 n^2 n2的判断必然超时

因为对于 a [ i ] ≤ 2 × 1 0 5 a[i]le2×10^5 a[i]≤2×105我们可用对 a [ i ] a[i] a[i]进行前缀和操作

前缀和 s u m [ i ] sum[i] sum[i]表示高度小于等于 i i i 的 a [ i ] a[i] a[i]的总个数

因此我们就可用每次记录一下 t o t a l + = s u m [ m a x n ] − s u m [ j − 1 ] total +=sum[maxn]-sum[j-1] total+=sum[maxn]−sum[j−1]

每次减去尽可能多的值即可

Code :

int sum[N];
int n,m;

void solve(){
	cin>>n>>m;
	int minn = INF , maxn  = 0 ;
	
	for(int i=1;i<=n;i++){
		int x;cin>>x;sum[x]++;
		//对区间按高度进行分类
		minn  = min(minn,x);
		maxn  = max(maxn,x);
	}
	
	for(int i=1;i<=maxn; i ++) sum[i] +=sum[i-1];
	//前缀和
	
	int res = 0 ;
	 
	for(int i= maxn ; i > minn;){
		int j = i ,  total = 0 ;
		
		while(j > minn && total + sum[maxn] - sum[j-1] <= m){
			total += sum[maxn]  - sum[j-1];
			j -- ;
		}
		++res;
		i = j ;
	}
	
	cout<
转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/879876.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号