牛客假日团队赛8
A Cell Phone Network
思路:最小支配集
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 10010;int p[N]; // 父节点编号
bool vis[N]; // dfs判重
int newpos[N]; // newpos[i]表示dfs序列的第i个点是哪个点
int now; // 表示dfs序列已有点数
bool s[N]; // 判断是否被覆盖
bool se[N]; // se[i]表示点i属于要求的集合
int head[N];
int n, u, v, ans, tot;struct node{int to, next;
}edge[N << 1];void dfs(int x){newpos[++ now] = x;for (int i = head[x]; i; i = edge[i].next){if (!vis[edge[i].to]){vis[edge[i].to] = true;p[edge[i].to] = x;dfs(edge[i].to);}}
}void greedy(){for (int i = n; i >= 1; i -- ){int t = newpos[i];if (!s[t]){if (!se[p[t]]){se[p[t]] = true;ans ++;}s[t] = true;s[p[t]] = true;s[p[p[t]]] = true;}}
}void add_edge(int u, int v){edge[++ tot].to = v;edge[tot].next = head[u];head[u] = tot;
}int main(){scanf("%d", &n);for (int i = 1; i < n; i ++ ){scanf("%d%d", &u, &v);add_edge(u, v);add_edge(v, u);}p[1] = 1, vis[1] = 1,dfs(1);greedy();printf("%d\n", ans);return 0;
}
B iCow
思路:模拟 题意明确 按着题目分配就行了
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 1010;int n, t, maxr, pos_, divi, rem;struct cow{int r, pos;
}cows[N];int main(){scanf("%d%d", &n, &t);for (int i = 1; i <= n; i ++ ){scanf("%d", &cows[i].r);cows[i].pos = i;}while (t -- ){maxr = 0;pos_ = 0;for (int i = 1; i <= n; i ++ ){if (cows[i].r > maxr){maxr = cows[i].r;pos_ = cows[i].pos;}}cows[pos_].r = 0;divi = maxr / (n - 1);rem = maxr % (n - 1);printf("%d\n", pos_);for (int i = 1; i <= n; i ++ ){if (i == pos_) continue;cows[i].r += divi;}for (int i = 1; i <= rem; i ++ ){if (i == pos_) rem ++;else cows[i].r += 1;}}return 0;
}
C 阶乘之和
思路:直接用python过的
AC代码
n = input()
n = int(n)
fact = 1
sum = 0
i = 1
while n >= i:fact = fact * isum = sum + facti = i + 1
print(sum)
D Artificial Lake
思路:模拟(队友写的
AC代码
#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <stack>
#include <cstdlib>
#include <queue>
#include <cmath>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <list>
#include <iterator>
#include <set>
#include <map>
#include <utility>
#include <iomanip>
#include <ctime>
#include <sstream>
#include <bitset>
#include <deque>
#include <limits>
#include <numeric>
#include <functional>
#define gc getchar()
#define mem(a) memset(a,0,sizeof(a))
#define mod 1000000007
#define sort(a,n,int) sort(a,a+n,less<int>())
#define fread() freopen("in.in","r",stdin)
#define fwrite() freopen("out.out","w",stdout)#define PI acos(-1.0)
#define N 100005
#define MOD 2520
#define E 1e-12typedef long long ll;
typedef char ch;
typedef double db;
const long long INF = 0x3f3f3f3f3f3f3f3f;using namespace std;struct node
{ll w , h;int l , r;
}a[N];int n = 0;
long long res[N] = {0};int lowest()
{ll minv = INF , pos = 0;for(int i = 1;i <= n;i++)if(a[i].h < minv){minv = a[i].h;pos = i;}return pos;
}
int update(int position)
{for(int i = 0;i<n;i++){int left = a[position].l , right = a[position].r;if(a[left].h < a[position].h)position = left;else if(a[right].h < a[position].h)position = right;elsereturn position;}
}
void guanshui(int position)
{int counter = 1;long long sum = 0;while(counter <= N){counter++;sum += a[position].w;res[position] = sum;int l = a[position].l , r = a[position].r;sum += (min(a[l].h , a[r].h) - a[position].h - 1) * a[position].w;a[l].r = r;a[r].l = l;if(a[l].h < a[r].h){a[l].w += a[position].w;position = l;}else{a[r].w += a[position].w;position = r;}position = update(position);}
}
int main()
{cin >> n;int position = 0;for(int i = 1;i <= n;i++){ cin >> a[i].w >> a[i].h;}for(int i = 0;i <= n+1;i++){a[i].l = i-1;a[i].r = i+1;}a[0].w = 1; a[0].h = INF; a[n+1].w = 1; a[n+1].h = INF;position = lowest();guanshui(position);for(int i = 1;i <= n;i++){cout << res[i] << endl;}return 0;
}
E Haybale Guessing
思路:并查集+区间染色
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 1e6 + 10;int n, q, ans;
int prt[N]; // prt[i] = j 表示区间 [j + 1, i] 被覆盖
int fa[N];struct node_{int l, r, A;
}seg[N];bool cmp(int a, int b){if (seg[a].A == seg[b].A){if (seg[a].l == seg[b].l) return seg[a].r < seg[b].r;return seg[a].l < seg[b].l;}return seg[a].A > seg[b].A;
}int find(int x){return fa[x] == x ? x : fa[x] = find(fa[x]);
}bool judge(int mid){for (int i = 1; i <= mid; i ++ ) prt[i] = i;for (int i = 1; i <= n; i ++ ) fa[i] = i;sort(prt + 1, prt + mid + 1, cmp);for (int i = 1; i <= mid; i ++ ){int A = seg[prt[i]].A;int l = seg[prt[i]].l, r = seg[prt[i]].r, L = l, R = r; // [l, r]为交集 [L, R]为并集while (i + 1 <= mid && A == seg[prt[i + 1]].A){++ i;if (seg[prt[i]].l > r) return false;l = max(l, seg[prt[i]].l);r = min(r, seg[prt[i]].r);L = min(L, seg[prt[i]].l);R = max(R, seg[prt[i]].r);}int x = find(l), y = find(r);if ((l != r && x == y && y != r) || (l == r && y != r)) return false;x = L, y = R;int flag = find(y + 1);while (flag != find(x)){int find_x = find(x);fa[find_x] = fa[find_x + 1];}}return true;
}int main(){scanf("%d%d", &n, &q);for (int i = 1; i <= q; i ++ )scanf("%d%d%d", &seg[i].l, &seg[i].r, &seg[i].A);int l = 1, r = q + 1;while (r - l > 1){int mid = (l + r) >> 1;if (judge(mid))l = mid;elser = mid;}if (l == q) ans = 0;else ans = l + 1;printf("%d\n", ans);return 0;
}
F Telephone Lines
思路:最短路 spfa+二分
AC代码
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 1010;queue<int> q;
int n, p, k, tot, u, v, w, l, r, mid, ans;
int head[N], dist[N];
bool vis[N];struct node{int to, w, next;
}edge[N << 5];inline void add_edge(int u, int v, int w){edge[++ tot].to = v;edge[tot].w = w;edge[tot].next = head[u];head[u] = tot;
}inline bool spfa(ll x){memset(dist, 0x3f, sizeof(dist));memset(vis, false, sizeof(vis));dist[1] = 0;vis[1] = true;q.push(1);while (!q.empty()){int u = q.front();q.pop();vis[u] = false;for (int i = head[u]; i; i = edge[i].next){int v = edge[i].to;if (dist[v] > dist[u] + (edge[i].w > x ? 1 : 0)){dist[v] = dist[u] + (edge[i].w > x ? 1 : 0);if (!vis[v]){vis[v] = true;q.push(v);}}}}return dist[n] <= k;
}int main(){l = 0, r = 0;ans = -1;scanf("%d%d%d", &n, &p, &k);for (int i = 1; i <= p; i ++ ){scanf("%d%d%d", &u, &v, &w);add_edge(u, v, w);add_edge(v, u, w);r = max(r, w);}while (l <= r){mid = (l + r) >> 1;if (spfa(mid)){ans = mid;r = mid - 1;}else l = mid + 1;}printf("%d\n", ans);return 0;
}
G Election Time
思路:排两次序就出来了
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 500010;int n, k;struct cow{int pos, a, b;
}cows[N];int cmp1(cow x, cow y){return x.a > y.a;
}int cmp2(cow x, cow y){return x.b > y.b;
}int main(){scanf("%d%d", &n, &k);for (int i = 1; i <= n; i ++ ){scanf("%d%d", &cows[i].a, &cows[i].b);cows[i].pos = i;}sort(cows + 1, cows + n + 1, cmp1);sort(cows + 1, cows + k + 1, cmp2);printf("%d\n", cows[1].pos);return 0;
}
H Costume Party
思路:数据很水 可以直接暴力过 可以二分或状态压缩
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 20010;int n, s, cnt, ans;
int L[N];int main(){scanf("%d%d", &n, &s);for (int i = 1; i <= n; i ++ ) scanf("%d", &L[i]);sort(L + 1, L + n + 1);for (int i = 1; i <= n; i ++ ){while (cnt + 1 < i && L[i] + L[cnt + 1] <= s) cnt ++;while (cnt >= 1 && L[i] + L[cnt] > s) cnt --;ans += cnt;}printf("%d\n", ans);return 0;
}
I Cantor表
思路:模拟
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}int n, k, s;int main(){scanf("%d", &n);while (s < n){k ++;s += k;}if (k & 1) printf("%d/%d\n", s - n + 1, n + k - s);else printf("%d/%d\n", n + k - s, s - n + 1);return 0;
}
J Running
思路:dp
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 20010;
const int M = 510;int n, m, ans;
int dp[N][M], d[N];int main(){scanf("%d%d", &n, &m);for (int i = 1; i <= n; i ++ ) scanf("%d", &d[i]);dp[1][1] = d[1];for (int i = 1; i <= n; i ++ ){for (int j = 0; j <= min(m, i); j ++ ){if (j == 0) dp[i][0] = max(dp[i][0], dp[i - 1][0]);else dp[i + j][0] = max(dp[i + j][0], dp[i][j]); // 休息dp[i + 1][j + 1] = max(dp[i + 1][j + 1], dp[i][j] + d[i + 1]); // 不休息}}
// for (int i = 0; i <= m; i ++ )
// printf("%d\n", dp[n][i]);ans = dp[n][0];printf("%d\n", ans);return 0;
}
K Cow Contest
思路:传递闭包 floyd就行
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}const int N = 110;
const int M = 4510;int n, m, u, v, cnt, ans;
int mp[N][N];int main(){scanf("%d%d", &n, &m);for (int i = 1; i <= m; i ++ ){scanf("%d%d", &u, &v);mp[u][v] = 1;}for (int k = 1; k <= n; k ++ )for (int i = 1; i <= n; i ++ )for (int j = 1; j <= n; j ++ )mp[i][j] = mp[i][j] || (mp[i][k] && mp[k][j]);for (int i = 1; i <= n; i ++ ){cnt = 0;for (int j = 1; j <= n; j ++ )if (mp[i][j] || mp[j][i])cnt ++;if (cnt == n - 1) ans ++;}printf("%d\n", ans);return 0;
}
L 幂次方
思路:模拟
AC代码
#include<stdio.h>
#include<iostream>
#include<math.h>
#include<algorithm>
#include<string.h>
#include<queue>
#include<set>
#include<string>
#include<sstream>
typedef long long ll;
typedef unsigned long long ull;
using namespace std;ll Pow_mod(ll a, ll b, ll c){ll ans = 1;a %= c;while (b){if (b & 1) ans = (ans * a) % c;a = (a * a) % c;b >>= 1;}return (ans % c);
}ll Pow(ll a, ll b){ll ans = 1;while (b){if (b & 1) ans *= a;a *= a;b >>= 1;}return ans;
}int gcd(int a, int b){return b ? gcd(b, a % b) : a;
}int lcm(int a, int b){return a * 1ll / gcd(a, b) * b;
}int n;
bool flag;
string s[16]={"2(0)", "2", "2(2)", "2(2+2(0))","2(2(2))", "2(2(2)+2(0))", "2(2(2)+2)", "2(2(2)+2+2(0))","2(2(2+2(0)))", "2(2(2+2(0))+1)", "2(2(2+2(0))+2)", "2(2(2+2(0))+2+2(0))","2(2(2+2(0))+2(2))", "2(2(2+2(0))+2(2)+2(0))", "2(2(2+2(0))+2(2)+2)", "2(2(2+2(0))+2(2)+2+2(0))"};int main(){scanf("%d", &n);for (int i = 15; i >= 0; i -- ){if (Pow(2, i) <= n){n -= Pow(2, i);if (flag) printf("+");cout<<s[i];flag = true;}}return 0;
}