秋季 CSP-S 第二场模拟赛(赛后总结)
今天国庆,打模拟赛。本来想打T2正解,结果想错了。直接暴0寄了。先把题目放上来吧。提交文件game.cpp输入文件game.in输出文件game.out时间空间限制:2秒, 512 MBAlice和Bob正在玩游戏。游戏规则如下:一开始有一个n个数的序列。Alice和Bob轮流进行操作。每次操作,Alice和Bob可以选择从序列的左边或者右边拿走一个数字。同时,需要满足当前操作拿走的数字比上一个被
·
今天国庆,打模拟赛。
本来想打T2正解,结果想错了。直接暴0寄了。
先把题目放上来吧。
第一题 游戏
提交文件
:
game.cpp
输入文件
:
game.in
输出文件
:
game.out
时间空间限制:
2
秒
, 512 MB
Alice
和
Bob
正在玩游戏。游戏规则如下:
一开始有一个
n
个数的序列。
Alice
和
Bob
轮流进行操作。每次操作,
Alice
和
Bob
可以选择从序列的
左边或者右边拿走一个数字。同时,需要满足当前操作拿走的数字比上一个被拿走的数字大,特别的,第一
个拿走的数字没有限制。谁不能操作谁就输了。
假设两个人都聪明绝顶,
Alice
先手,你可以告诉他们谁能赢吗?
输入格式
第一行一个整数,
n
表示序列长度。
第二行
n
个整数,表示序列。
输出格式
如果
Alice
必胜,则输出
Alice
。否则输出
Bob
。
样例数据
game.in
game.out
3
1 3 2
Bob
数据范围
对于
20
%
的数据,
2
≤
N
≤
20
。
对于另外
20
%
的数据,
2
≤
N
≤
100
,
1
≤
a
i
≤
100
对于另外
20
%
的数据,
2
≤
N
≤
1000
。
对于
100
%
的数据,
2
≤
N
≤
100000
,
1
≤
a
i
≤
100000
。
第二题 文本编辑器
提交文件
:
editor.cpp
输入文件
:
editor.in
输出文件
:
editor.out
时间空间限制:
2
秒
, 512 MB
你现在有一个奇怪的文本编辑器。该文件编辑器一行只可以存放
24
个字,一旦超过了这个字数就会换
行,当然,你也可以提前手动换行。
现在你有
n
句话,每一句话包含
a
i
个字。出于种种原因,你不希望一句话出现在两行里。
现在一共有两种操作:
1,
修改;将第
i
句话的字数改为
c
。
2.
询问:第
l
到第
r
句话依次输入到编辑器中,并且不存在一句话被分为两行,至少需要多少行。
输入格式
第一行两个数
n, m
,分别表示句子个数和操作次数。
第二行
n
个数,
a
i
表示第
i
个句子的字数。
接下来
m
行,每行第一个数为
op
,表示操作类型
.
若
op=1
,则接下来两个数
x,c
,表示一次修改。
若
op=2
,则接下来两个数
l,r
,表示一个询问。
输出格式
对于每个
op=2
的操作,输出一个数表示答案。
样例数据
editor.in
editor.out
5 5
8 8 9 12 13
2 1 5
2 2 4
1 5 3
2 1 5
2 2 5
3
2
2
2
数据范围
对于
30
%
的数据,
1
≤
n, m
≤
10
3
对于另外
20
%
的数据,
1
≤
a
i
, c
≤
10
对于另外
20
%
的数据,
1
≤
n, m
≤
5
∗
10
4
对于
100
%
的数据,
1
≤
n, m
≤
10
5
,
1
≤
l
≤
r
≤
n
,
1
≤
x
≤
n,
1
≤
a
i
, c
≤
24
第三题 路径染色
提交文件
:
painting.cpp
输入文件
:
painting.in
输出文件
:
painting.out
时间空间限制:
2
秒
, 512 MB
Z
国可以看作是一个
n
个点,
n-1
条道路组成的连通图,每一条
证任意两点间都至少有一条路径。
道路有长度,还有颜色。一开始所有的道路都是白色的。突然有一
过于单调了,于是他决定将某些道路染成黑色。不幸的是,由于种种
人来完成这个目标。具体来说,现在有
M
个机器人,第
i
个机器人所
一个终点
q
i
,然后机器人就会沿着最短的距离从
p
i
前往
q
i
。在前进的
取反,即白色变成黑色,黑色变成白色。当然,指定机器人运动是需
距离,就需要
1
的能量。
现在
Z
国的国王找到了你,他希望你能帮他计算出将所有道路染
不可能。
输入格式
第一行两个整数,
n,m
。分别表示
Z
国有
n
个点,
m
个机器人。
紧接着
n-1
行,每行四个整数
u,v,l,c
。表示存在有一条道路,连
c=0
,则表示着该道路希望被染成白色。如果
c=1
,则表示该道路希望
最后一行,有
m
个整数
p
i
,表示第
i
个机器人所在的位置。
输出格式
输出一行一个整数,表示最少需要多少能量。如果无法达到要求
样例数据
painting.in
pa
3 2
1 2 1 1
2 3 2 1
1 3
3
5 4
1 2 3 0
2 3 1 1
3 4 2 0
4 5 2 1
1 1 1 1
21
数据范围
对于
20
%
的数据,保证
n, m
≤
7
对于另外
20
%
的数据,保证
n, m
≤
100
对于另外
10
%
的数据,保证树的形态是一条链。
对于另外
10
%
的数据,保证
u=1
。
第四题 升级
提交文件
:
level.cpp
输入文件
:
level.in
输出文件
:
level.out
时间空间限制:
2
秒
, 512 MB
你现在玩一个氪金游戏。和大多数游戏一样,升级需要一定的经验。在这里,从第
i
−
1
级升到第
i
级需
要
a
i
点经验。如果你一共获得过
H
点经验,那么你的等级将会是最大的
L
,满足
H
≥
∑
L
i
=1
a
i
。
特别的是,这个游戏的升级只可以通过道具,每使用一个道具可以获得
v
点经验值。道具的价格随着等
级的升高而升高,具体来说,如果你当前在第
i
级,那么道具的价格为
w
i
。同时,你每次购买的道具不可以
超过
k
个,并且一经购买将会马上使用。换句话说,如果你在买完道具后升级了,那么道具就会自动涨价。
你现在是
1
级,你想知道升到第
n
级最少要花多少钱。
输入格式
第一行三个整数,分别表示
n
,
k
,
v
。具体含义见描述。
第二行
n
个整数
a
i
,表示升级所需的经验。保证
a
1
= 0
。
第三行
n
个整数
w
i
,表示第
i
级道具的价格。
输出格式
输出一行一个整数,表示最少需要多少钱。
样例数据
level.in
level.out
4 2 4
0 2 6 8
1 2 3 4
8
数据范围
对于
20
%
的数据,满足
n, k, a
≤
6
对于
50
%
的数据,满足
n
≤
1000
对于
100
%
的数据,
2
≤
n, k, v,
≤
100000
,
0
≤
a
i
, w
i
≤
1000000
,同时保证
w
和
a
均递增。
T1
我写了个玄学解法,tm测试样例都错了结果,还AC了这道题,就离谱。
#include<bits/stdc++.h>
using namespace std;
int a[100010];
deque<int> q;
bool dfs(int x,int last){
bool ans = 0,ans2 = 0;
if(x == 1)return 1;
int tmp_f = q.front(),tmp_b = q.back();
if(q.front() > last){
q.pop_front();
ans = dfs(x-1,tmp_f);
//for(int i = 0;i < q.size();i++)cout<<q.front()<<" ";
//cout<<x<<" "<<ans<<endl;
q.push_front(tmp_f);
if(ans == 0)return 1;
}
if(q.back() > last){
q.pop_back();
ans2 = dfs(x-1,tmp_b);
q.push_back(tmp_b);
//cout<<x<<" "<<ans2<<endl;
if(ans2 == 0)return 1;
}
if(ans2&&ans)return 0;
if(q.back() <= last &&q.back() <= last){
return 0;
}
}
int main(){
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
ios::sync_with_stdio(false);
int n;
cin>>n;
bool pd1 = 1,pd2 = 1;
for(int i = 1;i <= n;i++){
cin>>a[i];
q.push_back(a[i]);
}
if(dfs(n,0)){
cout<<"Alice";
}
else{
cout<<"Bob";
}
return 0;
}
好了,我发现我哪里挂掉了,这数据真水。
x = 1时不一定要return 1;
真AC代码
#include<bits/stdc++.h>
using namespace std;
int a[100010];
deque<int> q;
bool dfs(int x,int last){
bool ans = 0,ans2 = 0;
if(x == 1)return last < q.back()?1:0;
int tmp_f = q.front(),tmp_b = q.back();
if(q.front() > last){
q.pop_front();
ans = dfs(x-1,tmp_f);
q.push_front(tmp_f);
if(ans == 0)return 1;
}
if(q.back() > last){
q.pop_back();
ans2 = dfs(x-1,tmp_b);
q.push_back(tmp_b);
if(ans2 == 0)return 1;
}
if(ans2&&ans)return 0;
if(q.back() <= last &&q.back() <= last){
return 0;
}
}
int main(){
//freopen("game.in","r",stdin);
//freopen("game.out","w",stdout);
ios::sync_with_stdio(false);
int n;
cin>>n;
bool pd1 = 1,pd2 = 1;
for(int i = 1;i <= n;i++){
cin>>a[i];
q.push_back(a[i]);
}
if(dfs(n,0)){
cout<<"Alice";
}
else{
cout<<"Bob";
}
return 0;
}
T2 正解
考虑用线段树维护答案
一行不被分为两段,只需要能放就放,放不下就换行就是最优的
对于一段区间,我们只需要知道 表示前面已经有 个字符输入进来,之后会换多少行,以及最后的一行会剩下多少个字符就可以支持合并了。
用线段树维护
f
即可
复杂度
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+10;
int len,ed;//全局的作为答案
struct qq{
int len,ed;
};
struct sgt{
int s1,s2;
qq f[25];
}t[N*4];
int a[N],n,m;
void upd(int now){
int s1 = t[now].s1,s2 = t[now].s2;
for(int u = 0;u <= 24;u++){
qq p = t[s1].f[u] ;
qq q = t[s2].f[p.ed];
t[now].f[u].len = p.len+q.len;
t[now].f[u].ed = q.ed;
}
}
void build(int now,int l,int r){
if(l == r){
t[now].s1 = l,t[now].s2 = r;
for(int u = 0;u <= 24;u++){
if(u+a[l] <= 24)t[now].f[u] = qq{0,u+a[l]};
else t[now].f[u] = qq{1,a[l]};
}
return;
}
int mid = (l+r)/2;
t[now].s1 = now*2,t[now].s2 = now*2+1;
build(now*2,l,mid);
build(now*2+1,mid+1,r);
upd(now);
}
void query(int now,int begin,int end,int l,int r){
if(l == begin&&r == end){
len += t[now].f[ed].len;
ed = t[now].f[ed].ed;
return;
}
int mid = (begin+end)/2;
if(r <= mid)query(now*2,begin,mid,l,r);
else if(l > mid)query(now*2+1,mid+1,end,l,r);
else{
query(now*2,begin,mid,l,mid);
query(now*2+1,mid+1,end,mid+1,r);
}
return;
}
void change(int now,int begin,int end,int id,int x){
if(begin == end){
for(int u = 0;u <= 24;u++){
if(u+a[id] <= 24)t[now].f[u] = qq{0,u+a[id]};
else t[now].f[u] = qq{1,a[id]};
}
return;
}
int mid = (begin+end)/2;
if(id <= mid)change(now*2,begin,mid,id,x);
else change(now*2+1,mid+1,end,id,x);
upd(now);
}
int main(){
freopen("editor.in","r",stdin);
freopen("editor.out","w",stdout);
cin>>n>>m;
for(int i = 1;i<= n;i++){
cin>>a[i];
}
build(1,1,n);
for(int i = 1;i <= m;i++){
int op;
cin>>op;
if(op == 2){
int l,r;
cin>>l>>r;
ed = 0;
len = 1;
query(1,1,n,l,r);
cout<<len<<endl;
}
else{
int l,r;
cin>>l>>r;
a[l] = r;
change(1,1,n,l,r);
}
}
return 0;
}
wocao,你猜我调了多久。
T3
树形dp
对于一个子树,只会有机器人下来或者机器人出去中的一种状态
表示完成 这颗子树,还需要 个机器人走进来染完子树所需要的答案
表示完成 这颗子树,有 个机器人需要走出去染完子树所需要的答案
讨论一下可以得到 和 相互转移的转移式
T4
大暴力吧,考试肯定写不出正解。
更多推荐
已为社区贡献1条内容
所有评论(0)