覆盤:本場簽到題AB寫的略慢,B甚至沒把思路考慮清楚,就開始動鍵盤,E題也沒把思路考慮完整清楚。之前自身出現的問題是不懂一個思路遇到挫折就換一個思路,現在是沒把思路考慮完整,結合樣例考慮(正式比賽中還需要這樣自己想樣例的能力)。
A.Odd Selection
思路:我的思路統計奇數偶數個數的情況,只有奇數個奇數才能滿足此題條件,但是在這個條件的基礎上還需要滿足他的個數符合要求,標程寫的還是也還挺好的,但是像我就是會考慮個數的關係,其實沒有利用好計算機的特點;
int a[N];
int main(){
int T; scanf("%d" , &T);
for(int cas = 1 ; cas <= T ; cas ++){
int n , m ;
scanf("%d %d" , &n , &m);
int res1 = 0 ,res2 = 0;
for(int i = 1 ; i <= n ; i ++){
scanf("%d" ,&a[i]);
if(a[i] % 2 == 1) res1 ++;
else res2 ++;
}
if(res1 == 0){
puts("No");
continue;
}
if(m % 2 == 0){
if(res2 == 0){
puts("No");
continue;
}
if(res1 % 2 == 0){
if(res1 - 1 + res2 >= m)puts("Yes");
else puts("No");
}
else puts("Yes");
}
else{
if(res1 % 2 == 0){
if(res1 - 1 + res2 >= m)puts("Yes");
else puts("No");
}
else puts("Yes");
}
}
return 0;
}
B.Subsequence Hate
思路:沒考慮清楚的題之一,明明是00001111或者1111000的情況,但是卻只考慮了一個1;
int main(){
int T; scanf("%d" , &T);
for(int cas = 1 ; cas <= T ; cas ++){
string a;
cin >> a;
int ans = inf;
for(int i = 0 ; i <= SZ(a) ; i ++){
int res = 0 ,res1 = 0 ;
for(int j = i - 1;j >= 0 ; j --){
if(a[j] == '0') res ++;
else res1 ++;
}
for(int j = i ; j < SZ(a) ; j ++){
if(a[j] == '1') res ++;
else res1 ++;
}
ans = min(ans, res);
ans = min(ans, res1);
}
printf("%d\n",ans);
}
return 0;
}
C. Game On Leaves
思路:可以理解爲小博弈,除了關鍵節點剩下的ans個點再減1判斷奇偶,剛剛看了題解,我好像個小傻子,明明只需判斷就可以了,還寫了dfs。另附題解代碼。
vector<int>v[N];
int sz[N];
void dfs(int x,int fa = -1){
sz[x] = 1;
for(auto y :v[x]){
if(y == fa)continue;
dfs(y ,x);
sz[x] += sz[y];
}
}
int main(){
int T; scanf("%d" , &T);
for(int cas = 1 ; cas <= T ; cas ++){
int n ,pos;
scanf("%d %d" , &n, &pos);
for(int i = 1; i <= n ; i ++)v[i].clear();
for(int i = 1; i < n ; i ++){
int x, y;
scanf("%d %d" , &x , &y);
v[x].pb(y);
v[y].pb(x);
}
dfs(pos);
int maxx = -1 , ans = 0;
for(auto y : v[pos]){
maxx = max(sz[y] , maxx);
ans += sz[y];
}
if(SZ(v[pos]) == 1){
puts("Ayush");
}
else{
if((ans - 1)%2 == 1){
puts("Ashish");
}
else{
puts("Ayush");
}
}
}
return 0;
}
const int N = 2e5 + 5;
int n, x;
int deg[N];
vector<int> g[N];
int32_t main()
{
IOS;
int t;
cin >> t;
while(t--)
{
memset(deg, 0, sizeof(deg));
cin >> n >> x;
for(int i = 1; i <= n - 1; i++)
{
int u, v;
cin >> u >> v;
deg[u]++, deg[v]++;
}
if(deg[x] <= 1)
cout << "Ayush" << endl;
else
{
if(n % 2)
cout << "Ashish" << endl;
else
cout << "Ayush" << endl;
}
}
return 0;
}
D. Guess The Maximums
未補!!!!!!!!
E. Tree Shuffling
題意:根爲1的樹,對於任意一個點x,可以對這個點的子樹打亂k(k爲任意值)個節點的順序,滿足最後滿足現有值(1 or 0)和目標相同(1 or 0)花費a[x]*k,最後的最小花費。
思路:dfs回溯,最重要的思路點是若當前的節點的花費比向上到根節點的花費的最小值還要小,那麼就優先把此節點替換一下。就是回溯合併就行了,其他沒啥。
LL a[N];
int n;
int b[N], c[N];
int dp[N][3];
VI G[N];
LL ans;
void dfs(int x, int fa = -1 , LL cost = inf){
if(b[x] != c[x]){
dp[x][b[x]] ++;
}
for(auto y : G[x]){
if(fa == y) continue;
dfs(y , x , min(cost , a[x]));
dp[x][0] += dp[y][0];
dp[x][1] += dp[y][1];
}
LL res = min(dp[x][0], dp[x][1]);
if(a[x] <= cost){
ans += 2*res*a[x];
dp[x][0] -= res;
dp[x][1] -= res;
}
}
int main(){
while(~scanf("%d" , &n)){
memset(dp,0,sizeof dp);
for(int i = 1; i <= n ; i ++)G[i].clear();
for(int i = 1; i <= n ; i ++){
scanf("%lld %d %d",&a[i] , &b[i] , &c[i]);
}
for(int i = 1; i < n ; i ++){
int x,y ; scanf("%d %d" ,&x, &y);
G[x].pb(y) ; G[y].pb(x);
}
ans = 0 ;
dfs(1);
if(dp[1][0] + dp[1][1])puts("-1");
else printf("%lld\n",ans);
}
}