Codeforces 981 共同点路径覆盖树构造 BFS/DP书架&最大值
A
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 2e5 + 5; bool ok(string x) { int len = x.size(); if (len == 1) { return true; } for (int i = 0; i < x.size() / 2; i++) { if (x[i] != x[x.size() - 1 - i]) { return false; } } return true; } int main() { ios_base::sync_with_stdio(0); cin.tie(0); string a; cin >> a; int flag = 1; while (flag) { if (ok(a)) { if (a.size() == 1) { cout << 0 << endl; return 0; } a = a.substr(0, a.size() - 1); } else { flag = 0; } } cout << a.size() << endl; return 0; }
B
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 2e5 + 5; map<int,ll> mp; int main() { ios_base::sync_with_stdio(0); cin.tie(0); ll anser=0; int n,m; cin >> n; int a,b; for(int i=1;i<=n;i++) { cin >> a >> b; if(mp[a]<b) { anser+=b-mp[a]; mp[a]=b; } } cin >> m; for(int i=1;i<=m;i++) { cin >> a >> b; if(mp[a]<b) { anser+=b-mp[a]; mp[a]=b; } } cout<<anser<<endl; return 0; }
C
解:
构造题
很明显如果是有不小于一个的度大于2的点则No
如果没有度大于2的点则是一条链 直接输出两端 如果有的话则是菊花图 找每个度为1的叶子点与中心相连
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 1e5 + 5; vector<int> g[N]; int du[N]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); int n; cin >> n; int u, v; for (int i = 1; i < n; i++) { cin >> u >> v; g[u].pb(v), g[v].pb(u); du[u]++, du[v]++; } int sum = 0; int maxn = -1; int aim = 0; for (int i = 1; i <= n; i++) { if (du[i] > 2) { sum++; } if (du[i] > maxn) { aim = i; maxn = du[i]; } } if (sum > 1) { cout << "No" << endl; return 0; } if (maxn > 2) { cout << "Yes" << endl; int cnt=0; for(int i=1;i<=n;i++) { if(du[i]==1) { cnt++; } } cout << cnt << endl; for (int i = 1; i <= n; i++) { if (i == aim) { continue; } if (du[i] == 1) { cout << aim << " " << i << endl; } } } else { cout << "Yes" << endl; cout << 1 << endl; for (int i = 1; i <= n; i++) { if (du[i] == 1) { cout << i << " "; } } cout << endl; } return 0; }
D. Bookshelves
题意:
给你N个书K个书架,每个书有一个价值,要求你把书分成 连续的K段 分配进这K个书架使得这几个书架的总值 AND值 最大
解:
贪心 DP或者BFS
首先因为是AND操作所以我们要从最高位开始贪心 如果可行的话就 ans | =1 << i
DP:
/*Huyyt*/ #include<bits/stdc++.h> #define mem(a,b) memset(a,b,sizeof(a)) #define pb push_back using namespace std; typedef long long ll; typedef unsigned long long ull; const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}}; const int mod = 1e9 + 7; const int gakki = 5 + 2 + 1 + 19880611 + 1e9; const int N = 55 + 5; int n, K; ll sum[N][N]; ll a[N]; bool dp[N][N]; int main() { ios_base::sync_with_stdio(0); cin.tie(0); cin >> n >> K; for (int i = 1; i <= n; i++) { cin >> a[i]; sum[i][i] = a[i]; for (int j = i - 1; j >= 1; j--) { sum[j][i] = sum[j + 1][i] + a[j]; } } //sum[i][j]表示从第i位到第j位的前缀和 ll ans = 0; for (int w = 60; w >= 0; w--) //从最高位开始贪起 { mem(dp, 0); //每一次要初始化 dp[0][0] = 1; //dp[i][j]表示把前N个数分成j块每块都有 1<<w 是否可以 for (int i = 1; i <= n; i++) { for (int j = i - 1; j >= 0; j--) { for (int k = 1; k <= K; k++) { //如果从前的位置j满足可以分为k-1块而且从j+1到i的前缀和包含了之前贪心的答案同时1<<w位为1 if (dp[j][k - 1] && (sum[j + 1][i]&ans) == ans && ((sum[j + 1][i] >> w) & 1)) { dp[i][k] = 1; } } } } if (dp[n][K]) { ans |= 1LL << w; } } cout << ans << endl; return 0; }
BFS
E. Addition on Segments