今天国庆,打模拟赛。

本来想打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_i表示前面已经有 i个字符输入进来,之后会换多少行,以及最后的一行会剩下多少个字符就可以支持合并了。
用线段树维护 f 即可
复杂度O(24n logn)
#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

对于一个子树,只会有机器人下来或者机器人出去中的一种状态
表示完成 f_{i,j}这颗子树,还需要j 个机器人走进来染完子树所需要的答案
表示完成 g_{i,j}这颗子树,有 i个机器人需要走出去染完子树所需要的答案
讨论一下可以得到 f_{i,j}f_{i,j} 相互转移的转移式

T4

大暴力吧,考试肯定写不出正解。

Logo

欢迎加入我们的广州开发者社区,与优秀的开发者共同成长!

更多推荐