A
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 1e5 + 10;
int main(){
int a, b; scanf("%d%d", &a, &b);
int cnt = 1;
while(true){
if(cnt & 1){
if(a < cnt) break;
a -= cnt;
}else{
if(b < cnt) break;
b -= cnt;
}
cnt++;
}
if(cnt & 1) puts("Vladik");
else puts("Valera");
return 0;
}
B
看到n,m的范围刚开始还是不敢试,后面过了很多之后就试了一发
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 1e5 + 10;
int num[qq];
bool vis[qq];
int main(){
int n, m; scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf("%d", num + i);
if(i == num[i]) vis[i] = true;
}
while(m--){
int a, b, c; scanf("%d%d%d", &a, &b, &c);
int cnt = 0;
for(int i = a; i <= b; ++i)
if(num[i] > num[c]) cnt++;
if(cnt == b - c) puts("Yes");
else puts("No");
}
return 0;
}
C
题意:给出n,然后n个数,要你选择一些不相交的区间,使得这些区间的异或的和最大,区间有这样的限制,对于区间的任何数,其余相同的数都要在这个区间,否者这个区间就是不合法的。
思路:求出每个数出现的最左端和最右端,定义dp[i]为1到i这个区间所能选出的最大值,然后枚举右端点,找合法的左端点即可
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define mst(a, b) memset(a, b, sizeof a)
#define pill pair<int, int>
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 5000 + 5;
int num[qq];
int l[qq], r[qq];
int dp[qq];
int vis[qq];
int n;
int main(){
scanf("%d", &n);
mst(l, -1);
for(int i = 1; i <= n; ++i){
scanf("%d", num + i);
if(l[num[i]] == -1){
l[num[i]] = r[num[i]] = i;
}else{
r[num[i]] = i;
}
}
for(int i = 1; i <= n; ++i){
dp[i] = dp[i - 1];
mst(vis, 0);
int st = i, ans = 0;
for(int j = i; j >= 1; --j){
if(vis[num[j]] == 0){
if(r[num[j]] > i) break;
if(l[num[j]] < st) st = l[num[j]];
ans ^= num[j];
vis[num[j]] = 1;
}
if(j == st){
dp[i] = max(dp[i], dp[j - 1] + ans);
}
}
}
printf("%d\n", dp[n]);
return 0;
}
D
题意:给出一个n*m的迷宫,从(1, 1)要走到F, 你每次可以给系统一个方向,L,R,U,D, 然后系统会返回给你一个坐标,代表执行这个方向后所到达的坐标,现在让你模拟这个过程。但是U和D可能会互换功能(也就是说你给出U,但实际执行的是D), L和R也可能互换。
思路:首先bfs找出一个可行解然后按着这个坐标去走,分析可知,实际上系统是不会给你返回-1 -1这种坐标的,因为你第一次从(1, 1)出去的时候即可知道某个方向是否有交换,在你第一次转弯的时候即可发现另一个方向是否交换(不会走出边界,如果所给操作走出边界的话会返回原坐标)
#include <bits/stdc++.h>
using namespace std;
#define LL long long
#define pb push_back
#define pill pair<int, int>
#define mst(a, b) memset(a, b, sizeof a)
#define REP(i, x, n) for(int i = x; i < n; ++i)
const int qq = 105;
char graph[qq][qq];
int path[qq][qq];
int dx[] = {-1, 1, 0, -0};
int dy[] = {0, -0, -1, 1};
char op[] = {'U', 'D', 'L', 'R'};
int n, m, sx, sy;
void Bfs(){
queue<pill> Q;
Q.push(pill(1, 1));
mst(path, -1);
path[1][1] = 0;
while(!Q.empty()){
pill t = Q.front();
Q.pop();
// printf("%d %d\n", t.first, t.second);
if(graph[t.first][t.second] == 'F'){
sx = t.first;
sy = t.second;
break;
}
for(int i = 0; i < 4; ++i){
int a = t.first + dx[i];
int b = t.second + dy[i];
// printf("%d %d %d %c\n", a, b, path[a][b], graph[a][b]);
if(a < 1 || b < 1 || a > n || b > m) continue;
// printf("111\n");
if(graph[a][b] == '*' || path[a][b] != -1) continue;
// printf("222\n");
path[a][b] = i + 1;
Q.push(pill(a, b));
}
}
}
int x[qq * qq], y[qq * qq];
int tot;
void Dfs(int a, int b){
tot = 0;
while(true){
x[tot] = a, y[tot] = b;
// printf("%d %d\n", a, b);
tot++;
if(a == 1 && b == 1) break;
if(path[a][b] == 1){
a += 1;
}else if(path[a][b] == 2){
a -= 1;
}else if(path[a][b] == 3){
b += 1;
}else if(path[a][b] == 4){
b -= 1;
}
}
}
int main(){
scanf("%d%d", &n, &m);
for(int i = 1; i <= n; ++i){
scanf("%s", graph[i] + 1);
}
Bfs();
// return 0;
Dfs(sx, sy);
// for(int i = tot - 1; i >= 0; --i)
// printf("%d %d\n", x[i], y[i]);
tot = tot - 1;
while(tot > 0){
int j;
for(j = 0; j < 4; ++j){
if(x[tot] + dx[j] == x[tot - 1] && y[tot] + dy[j] == y[tot - 1]){
printf("%c\n", op[j]);
fflush(stdout);
int a, b; scanf("%d%d", &a, &b);
// if(a == -1 && b == -1) return 0;
if(a != x[tot - 1]){
swap(op[0], op[1]);
break;
}
if(b != y[tot - 1]){
swap(op[2], op[3]);
break;
}
tot--;
break;
}
}
}
return 0;
}