CCF CSP 202203-2 出行计划(C++满分+BIT极限优化)

题目

试题编号202203-2
试题名称出行计划
时间限制1.5s
内存限制512MB
问题描述在这里插入图片描述
输入输出在这里插入图片描述
样例1在这里插入图片描述
样例说明在这里插入图片描述

题目分析

如果你暴力去做,即在每次输入q时判断: q + k ≤ t i < q + k + c i ( i ∈ [ 1 , n ] ) q+k\leq t_i < q+k+c_i (i\in[1,n]) q+kti<q+k+cii[1,n]
这样肯定会超时,因为n和m的规模都在 1 0 5 10^5 105,要求解 1 0 10 10^{10} 1010太慢了。


换个思路,把上面的等式变换一下,针对于每个活动i,可以计算出活动i的合法时间 q q q
t i − k − c i < q i ≤ t i − k t_i-k-c_i <q_i\leq t_i-k tikci<qitik也就是说对于每一个活动i,有一个合法时间区间 [ t i − k − c i + 1 , t i − k ] [t_i-k-c_i+1,t_i-k] [tikci+1,tik]是可以满足题意的。

  1. 先建立一个表示时间轴的数组c[200005]。初始化为0.
  2. 对于每一个活动 ( t i , c i ) (t_i,c_i) (ti,ci),将 [ t i − k − c i + 1 , t i − k ] [t_i-k-c_i+1,t_i-k] [tikci+1,tik]在c数组中+1。表示该时间点是可满足活动i的。
  3. 在m个查询q的时候,直接访问c[q]就可以了,c[q]的值表示的就是可满足的活动数量。

分析

  1. 要注意 [ t i − k − c i + 1 , t i − k ] [t_i-k-c_i+1,t_i-k] [tikci+1,tik]更新区间要在大于等于1的时间下进行。
  2. 算法优化:要知道每次更新长度为 [ t i − k − c i + 1 , t i − k ] [t_i-k-c_i+1,t_i-k] [tikci+1,tik]的数组,执行n个活动是可以满足题意的,但是还是太慢了!!!一个好的算法怎么容忍这种线性时间的更新呢?所以总结下我们的方法的特征。
    (1) 区间更新 (2)定点查询
    你想到了什么?没错!线段树或者BIT。我用的是BIT可以达到:在这里插入图片描述
    60ms即可解决。一般来说BIT是定点更新区间查找。改一下就行了。让 s u m ( n ) = ∑ 1 n ( t [ i ] − t [ i − 1 ] ) = t [ n ] sum(n)=\sum_1^n(t[i]-t[i-1])=t[n] sum(n)=1n(t[i]t[i1])=t[n]区间[l,r]更新的时候只需要更新 u p d a t e ( l , 1 ) , u p d a t e ( r + 1 , − 1 ) update(l,1),update(r+1,-1) update(l,1)update(r+1,1)注意到区别,原来的BIT每个c[i]存储的是a[i],现在是存储a[i]-a[i-1],差分的思想,需要了解一下。

AC代码

#include <stdio.h>
#include <string.h>
#define rep(i,a,n) for(int i=a;i<n;i++)
#define mem(a) memset(a,0,sizeof(a))
#define max(a,b) ((a)>(b)?(a):(b))
using namespace std;
int c[200005];
int _n,m,k,t,cc,ans,l,r,q;
const int n=200005;
int lowbit(int i){
	return i&(-i);
}
void update(int i,int x){
	while(i<=n){
		c[i]+=x;
		i+=lowbit(i);
	}
}
int sum(int i){
	int ans=0;
	while(i>0){
		ans+=c[i];
		i-=lowbit(i);
	}
	return ans;
}
int main(){
	mem(c);
	scanf("%d%d%d",&_n,&m,&k);
	rep(i,1,_n+1){
		scanf("%d%d",&t,&cc);
		l=t-k-cc;
		r=t-k;//[l+1,r]
		if(l+1>=1){
			update(l+1,1);
			update(r+1,-1);
		}
		else if(l+1<1&&r>=1){
			update(1,1);
			update(r+1,-1);		
		}		
	}
	while(m--){
		scanf("%d",&q);
		printf("%d\n",sum(q));
	}
	return 0;
}
/*
6 2 10
5 24
10 24
11 24
34 24
35 24
35 48
1
2
*/
  • 16
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
根据引用\[1\]和引用\[3\]的信息,我们可以得知顿顿需要在n天时间内完成m项科目的加强训练。每项科目有一个编号,编号为i,其中1≤i≤m。每项科目的训练时间为ti天,即从第a天开始训练科目i,训练将持续到第a+ti−1天。科目之间存在依赖关系,如果科目i依赖科目j,那么只能在科目j训练结束后,科目i才能开始训练。 对于csp202212-2题目中的c++训练计划,我们需要知道c++训练的编号以及训练的时间。根据题目描述,我们可以得知c++训练的编号为2。然而,题目中没有提供c++训练的具体时间。因此,我们无法确定c++训练的时间。 综上所述,我们无法确定c++训练的具体计划。 #### 引用[.reference_title] - *1* *3* [CCF CSP 202212-2 训练计划C++)](https://blog.csdn.net/qq_46092061/article/details/129207826)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [CCF-CSP真题《202212-2 训练计划》思路+python题解](https://blog.csdn.net/weixin_53919192/article/details/129084465)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^insertT0,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值