A
我们发现满足就是,所以输出就行了,注意特判
CODE
#include <algorithm> #include <cctype> #include <cmath> #include <complex> #include <cstdio> #include <cstring> #include <deque> #include <functional> #include <list> #include <map> #include <iomanip> #include <iostream> #include <queue> #include <set> #include <stack> #include <string> #include <vector> using namespace std; #define int long long #define I inline #define ri register int #define For(i , x , y) for(ri i = x ; i <= y ; ++ i) #define Next(i , x) for(ri i = head[x] ; i ; i = e[i].nxt) #define pb(x) push_back(x) #define lowbit(x) x & -x I int read() { int s = 0 , w = 1; char ch = getchar(); while(ch < 48 || ch > 57) {if(ch == '-') w = -1; ch = getchar();} while(ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48) , ch = getchar(); return s * w; } int n; signed main() { cin >> n; if(n == 1) { puts("2") ; return 0; } cout << n + n - 1 << endl; return 0; }
B
我们发现不变越大时,越小,越大。
这里提供一个乱搞的贪心做法:我们将每一个数转化为二进制,每一位拆开,某一位上的数,预处理前缀和,首先枚举,如果顺序枚举的话肯定会超时,我们枚举二进制下是1的那一位上的那个数列上之后第一个是的位置,作为的位置,不难证明这是正确的。
时间复杂度
CODE
#include <algorithm> #include <cctype> #include <cmath> #include <complex> #include <cstdio> #include <cstring> #include <deque> #include <functional> #include <list> #include <map> #include <iomanip> #include <iostream> #include <queue> #include <set> #include <stack> #include <string> #include <vector> using namespace std; #define int long long #define I inline #define ri register int #define For(i , x , y) for(ri i = x ; i <= y ; ++ i) #define Next(i , x) for(ri i = head[x] ; i ; i = e[i].nxt) #define pb(x) push_back(x) #define lowbit(x) x & -x I int read() { int s = 0 , w = 1; char ch = getchar(); while(ch < 48 || ch > 57) {if(ch == '-') w = -1; ch = getchar();} while(ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48) , ch = getchar(); return s * w; } const int N = 1e5 + 5; int n , a[N] , to[20][N] , sum[N] , s[21][N] , Ans; I int calc_and(int l , int r) { int res = 0; For(i , 0 , 20) { if(s[i][r] - s[i][l - 1] == r - l + 1) res += pow(2 , i); } return res; } signed main() { //freopen("1.in" , "r" , stdin); n = read(); For(i , 1 , n + 1) { if(i <= n) a[i] = read() , sum[i] = sum[i - 1] + a[i]; For(j , 0 , 20) { if( !( (a[i] >> j) & 1 ) && ((a[i - 1] >> j) & 1)) { for(int k = i - 1 ; k >= 1 ; -- k) { if(!( (a[k] >> j) & 1 )) break; to[j][k] = i - 1; } } s[j][i] = s[j][i - 1] + ( (a[i] >> j) & 1 ); } } For(i , 1 , n) { Ans = max(Ans , a[i] * a[i]); For(j , 0 , 20) if((a[i] >> j) & 1) { Ans = max(Ans , (sum[to[j][i]] - sum[i - 1]) * calc_and(i , to[j][i])); } } cout << Ans << endl; return 0; } /* 10 2 3 12 4 212 4 2 1 3 33 */
D
直接爆搜。
当两个点有直接相连的边时,假设他们在一个团里,那么显然和他们相连的点都要与两个点都直接相连,所以我们就去找到某个点,和两个点中一个相连一个不相连。枚举删边加边即可。
E
这不是原题吗。
二分一个答案,判定的时候贪心地条,判断需要移动的石头是否符合题意
CODE
#include<bits/stdc++.h> using namespace std; #define ll long long #define R register int const int N = 5e5 + 5; inline int read() { int s = 0 , w = 1; char ch = getchar(); while(ch < 48 || ch > 57) {if(ch == '-') w = -1; ch = getchar();} while(ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48) ,ch = getchar(); return s * w; } int n , m , ans , a[N]; inline bool judge(int mid) { R i , j = 0 , cnt = 0; for(i = 1 ; i <= n ; ++ i) if(a[i] - a[j] >= mid) j = i , ++ cnt; if(a[n + 1] - a[j] < mid) -- cnt; return cnt >= n - m; } int main() { // freopen("stone.in","r",stdin); // freopen("stone.out","w",stdout); R i ; int mid , l = 1 , r = read(); n = read() , m = read(); for(i = 1 ; i <= n ; ++ i) a[i] = read(); a[n + 1] = r; while(l <= r) { mid = (l + r) >> 1; if(judge(mid)) ans = mid , l = mid + 1; else r = mid - 1; } cout << ans << endl; fclose(stdin); fclose(stdout); return 0; }
F
显然树上经过一条边的路径数量是这条边两边的点数之积,计算经过每条边的路径数量然后排序从大到小染色即可。
#include <algorithm> #include <cctype> #include <cmath> #include <complex> #include <cstdio> #include <cstring> #include <deque> #include <functional> #include <list> #include <map> #include <iomanip> #include <iostream> #include <queue> #include <set> #include <stack> #include <string> #include <vector> using namespace std; #define int long long #define I inline #define ri register int #define For(i , x , y) for(ri i = x ; i <= y ; ++ i) #define Next(i , x) for(ri i = head[x] ; i ; i = e[i].nxt) #define pb(x) push_back(x) #define lowbit(x) x & -x I int read() { int s = 0 , w = 1; char ch = getchar(); while(ch < 48 || ch > 57) {if(ch == '-') w = -1; ch = getchar();} while(ch >= 48 && ch <= 57) s = (s << 1) + (s << 3) + (ch ^ 48) , ch = getchar(); return s * w; } const int N = 1e6 + 5; int n , head[N] , tot , f[N] , a[N]; struct Edge { int to , nxt; } e[N << 1]; I void addedge(int x , int y) { e[++ tot] = (Edge) {y , head[x]} , head[x] = tot; } I void dfs(int u , int par) { f[u] = 1; Next(i , u) { int v = e[i].to; if(v == par) continue; dfs(v , u) ; f[u] += f[v]; } if(f[u] && f[u] != n) a[++ tot] = f[u] * (n - f[u]); } signed main() { n = read(); For(i , 1 , n - 1) { int u = read() , v = read(); addedge(u , v) ; addedge(v , u); } tot = 0 ; dfs(1 , 1); sort(a + 1 , a + tot + 1 , greater <int> ()); int Ans = 0; //For(i , 1 , tot) printf("%d \n" , a[i]); For(i , 1 , tot) Ans += a[i] * i; cout << Ans << endl; return 0; }