C
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#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 MOD = 1e9 + 7;
const int qq = 2e5 + 10;
LL sum[qq];
int main(){
int n; scanf("%d", &n);
for(int i = 1; i <= n; ++i){
scanf("%lld", sum + i);
sum[i] += sum[i - 1];
}
LL minx = 1e18;
for(int i = 1; i < n; ++i){
minx = min(minx, abs(sum[i] - (sum[n] - sum[i])));
}
printf("%lld\n", minx);
return 0;
}
D
题意:n个节点n-1条边组成的一棵树,首先1是黑色,n是白色,黑色可以染黑色的相邻节点,白色同理,问最后谁染的节点多,黑色先手。
思路:1到n节点实际上只有一条路径,那么抢占这一条路径上的节点成了决策关键性,我的方法是以1节点为根节点建树,然后模拟1和n染色过程,n染色的最后一个节点,以这个节点为根节点的所有节点即为白色,否则是黑色
#include <cstdio>
#include <cstring>
#include <map>
#include <algorithm>
#include <iostream>
#include <vector>
using namespace std;
#define LL long long
#define pb push_back
#define mk make_pair
#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 MOD = 1e9 + 7;
const int qq = 2e5 + 10;
vector<int> vt[qq];
int n, a, b;
int dp[qq], num[qq];
int pre[qq];
bool vis[qq];
void Dfs(int v, int fa, int dis){
dp[v] = dis;
pre[v] = fa;
for(int i = 0; i < (int)vt[v].size(); ++i){
int u = vt[v][i];
if(u == fa) continue;
Dfs(u, v, dis + 1);
num[v] += num[u];
}
num[v] = num[v] + 1;
}
int node[qq];
int main(){
scanf("%d", &n);
REP(i, 1, n - 1){
scanf("%d%d", &a, &b);
vt[a].pb(b), vt[b].pb(a);
}
Dfs(1, -1, 0);
int cnt = 0;
int x = n;
while(pre[x] != -1){
node[++cnt] = x;
x = pre[x];
}
node[++cnt] = 1;
int l = 1, r = cnt;
while(l < r){
if(l + 1 >= r - 1) break;
l++, r--;
}
int F, S;
F = S = 0;
S = num[node[l]];
F = n - S;
if(F > S) puts("Fennec");
else puts("Snuke");
return 0;
}