太戈编程[寒]C201-L6

[寒]C201-L6

                                                    650. 椅子危机

题目描述

你作为校长,正在筹办校园开放日,希望邀请学生和家长来参观,期间有n个公开课在不同教室开展。第i个公开课从时刻si分钟到时刻ti分钟,需要摆放xi把椅子。椅子从一个教室搬到另一个教室需要5分钟(假设人手足够多,不管搬几把椅子都是这个时间)。请问至少需要几把椅子?

输入输出格式

输入格式

输入文件为chair.in,输入第一行为正整数n,之后n行每行三个正整数si,ti,xi

输出格式

输出文件为chair.out,输出一个整数表示答案

输入输出样例

输入样例#1:

3

1 2 100

7 8 101

12 13 102

输出样例#1:

203

输入样例#2:

4

1 5 100

10 20 50

5 10 1

1 2 10

输出样例#2:

111

说明

样例说明: 样例1:课程1需要100把椅子,下课后都挪到课程2,课程2还需要额外1把。课程2来不及搬到课程3,所以课程3需要额外的102把椅子。共100+1+102=203把 样例2:课程1需要100把椅子,课程4需要10把椅子,课程1下课后搬到课程2,课程3必须自备1把椅子。共100+10+1=111把 数据规模: 对于50%的数据,1<=n<=500 对于75%的数据,1<=n<=2000 对于100%的数据,1<=n<=10000,si,ti,xi<=1000

模型元素:讲座(连续时间段)

输入样例

3

1 2 100

7 8 101

12 13 102

每个讲座的时间对应一个连续段,也就是区间

讲座开始时间是区间的左端点

讲座结束时间是区间的右端点

模型元素:椅子移动要5分钟

等等效于

算法1:模拟+计数器数组

输入第一行为正整数n,n<=10000,之后n行每行三个正整数si,ti,xi,保证都不超过1000。

时间范围很小

cnt[i]记录时刻i

需要多少把椅子

O(NR)

代码:100分

#include<bits/stdc++.h>
using namespace std;
const int N=10009;
int n,cnt[N],s,t,x;
int main(){
freopen("chair.in","r",stdin);
freopen("chair.out","w",stdout);
cin >> n;
for(int i = 0;i < n;i++){
cin >> s >> t>> x;
for(int j = s;j <= t+4;j++){
cnt[j] += x;
}
}
cout << *max_element(cnt,cnt+N) << endl;
return 0;
}

算法2:差分   区间两端打标记

代码:100分

#include<bits/stdc++.h>
using namespace std;
const int N=10009;
const int R=1009;
int d[N],s[N],n;
int main(){
    freopen("chair.in","r",stdin);
    freopen("chair.out","w",stdout);
   cin>>n;
   int a,b,x;
for(int i=1;i<=n;i++){
cin>>a>>b>>x;
       d[a]+=x;
d[b+5]-=x;
    }
for(int i=1;i<R;i++)//依次扫描
s[i]=s[i-1]+d[i];
cout<<*max_element(s+1,s+R)<<endl;
   return 0;
}

736. 汪星人

题目描述

你是一只汪星人,地球毁灭后你回到了汪星,这里每天有n个小时,你需要为自己选择正好连续的m小时作为每天睡眠的时间。从凌晨开始,第i小时内的睡眠质量为xi,请问经过选择后,你的睡眠质量总和最大是多少?

输入输出格式

输入格式

输入文件dog.in输入第一行为正整数n,m,1<=m<=n<=100000. 第二行为n个整数依次代表每小时的睡眠质量,绝对值均不超过100

输出格式

输出文件dog.out输出一个整数

输入输出样例

输入样例#1:

5 2

1 -1 -1 -1 2

输出样例#1:

3

方法1:断环+拉直+克隆 

断环+拉直+克隆 

-1

2

-3

1

7

-2

4

5

-1

2

-3

1

7

-2

4

5

断环+拉直+克隆

正整数n,m, 1<=m<=n<=100000

const int N=1000009;

int x[N],s[N],n,m;

高频易错点:环形问题克隆时,数组大小需要翻倍

代码:100分

#include<bits/stdc++.h>
using namespace std;
const int N=1000009;
int x[N],s[N],n,m;
int main(){
freopen("dog.in","r",stdin);
freopen("dog.out","w",stdout);
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> x[i];
}
for(int i = n + 1;i <= n*2;i++){
x[i] = x[i-n];
}  
s[0] = 0;
for(int i = 1;i <= n*2;i++){
s[i] = s[i - 1] + x[i];
}
int ans = s[m];
for(int i = m + 1;i <= n*2;i++){
ans = max(ans,s[i]-s[i-m]);
}
cout << ans << endl;
return 0;
}

方法2:首尾情况分类

首尾情况分类 

首尾不相连

首尾相连

首尾不相连:

-1

2

-3

1

7

-2

4

5

环形问题简化为直线型

首尾相连:

-1

2

-3

1

7

-2

4

5

左侧共i个    右侧共m-i个

||    ||         ||       ||

1    i        n-m+i       n

2种解释 

加法:s[i] + (s[n]-s[n-m+i])

减法:s[n] – (s[n-m+i]-s[i])

补集转换

代码:100分

#include<bits/stdc++.h>
using namespace std;
const int N=1000009;
int x[N],s[N],n,m;//定义两个数组x和s+int类型的n和m
int main(){
freopen("dog.in","r",stdin);
freopen("dog.out","w",stdout);
cin>>n>>m;
for(int i = 1;i <= n;i++){
cin >> x[i];//输入
}
for(int i = n + 1;i <= n*2;i++){
x[i] = x[i-n];//克隆数组
}  
s[0]=0;
for(int i = 1;i <= n*2;i++){
s[i] = s[i - 1] + x[i];//计算s[i]数组的前缀和
}
int ans = s[m];//ans初始化
for(int i = m + 1;i <= n*2;i++){
ans = max(ans,s[i]-s[i-m]);//打擂台找出最大值
}
cout<<ans<<endl;//输出答案
return 0;
}

2667. 高手集训

题目描述

太戈编程团队聚集了本市众多的编程高手。你作为总教练,要为高手们安排集训计划。课程表里有连续的n天可以供你选择,每天都有专题课程。其中第i天的专题趣味程度为h[i]。假设你选择了其中连续的若干天,从第l天到第r天。那么,

训练效果 = h[l]*1 + h[l+1]*2 + ... + h[r]*(r-l+1)

随着训练的深入进行,每天的趣味程度会得到更多倍数的效果。

目前有m种训练方案,每种方案由起始时间和结束时间来描述。请对每种方案输出训练效果。

输入输出格式

输入格式

输入文件training.in,输入第一行为正整数n和m, 均不超过100000。第二行为n个正整数代表每天专题的趣味程度,均不超过100000。随后共m行,每行为两个正整数l,r, 保证1<=l<=r<=n。

输出格式

输出文件training.out,输出一行共m个整数,由空格隔开。

输入输出样例

输入样例#1:

3 2

5 6 7

1 3

2 3

输出样例#1:

38 20

【说明】5*1+6*2+7*3=38;6*1+7*2=20。

代码:100分

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 100009;
ll n, m, h[N], s[N], g[N];
int main(){
freopen("training.in", "r", stdin);
freopen("training.out", "w", stdout);
cin >> n >> m;
for (ll i=1; i<=n; i++) cin >> h[i];
for (ll i=1; i<=n; i++){
s[i] = s[i-1] + h[i];
g[i] = g[i-1] + h[i] * i;
}
for (ll i=1; i<=m; i++){
ll l, r;
cin >> l >> r;
ll ans = g[r] - g[l-1] - (s[r] - s[l-1]) * (l-1);
cout << ans << " ";
}
return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值