牛客假日团队赛8

牛客假日团队赛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
", 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
", 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 * i
    sum = sum + fact
    i = 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-12
 
typedef 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;
        else
            return 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;
        else
            r = mid;
    }
    if (l == q) ans = 0;
    else ans = l + 1;
    printf("%d
", 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
", 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
", 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
", 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
", s - n + 1, n + k - s);
    else printf("%d/%d
", 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
", dp[n][i]);
    ans = dp[n][0];
    printf("%d
", 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
", 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;
}
原文地址:https://www.cnblogs.com/Misuchii/p/11287033.html