码迷,mamicode.com
首页 > 其他好文 > 详细

福州大学第十二届程序设计竞赛题解

时间:2015-05-04 06:28:46      阅读:155      评论:0      收藏:0      [点我收藏+]

标签:

A:这题利用单调栈,先预处理出每个位置向下的最远位置,那么每一行单独考虑,每行就相当于一些段的子矩阵个数,利用单调栈维护,每次出栈的时候把大于当前要入栈(高度0的不入栈了)的段的部分计算出来,累加一下答案即可

B:这题可以枚举,因为一个10^15开3方之后是10^5枚举起来是没有问题的,然后枚举一个数字i,等于要计算在max(a, i * i * i)到min(i * i * i, b)区间,有多少个x满足i * i * x在区间内,两边除下减下就能计算出答案了

C:并查集,注意每次合并的时候都要让城市作为根,最后对于人和服务找根,如果根的范围是城市,就表明信息是是全的

D:水题,用字符串存浮点数去计算,gcd约分下即可

E:这题。。显然没有很奇葩的数据,于是只要把不能互相在一个集合的连边,然后利用二分图染色判定,如果矛盾就无解,如果不矛盾,每次就取一个子集内黑白点多的一边累加,得到的答案就是最终答案

F:树形DP,dp[u][0]和dp[u][1]分别表示不回,回树根的最小代价,那么对于一个子树,回树根的代价是固定的,就是他的子树代价+边权,那么不回的代价就是任意选一个子树不回,这样的话,只要在找子节点的过程中,记录这个答案的最大值,那么用dp[u][1]减去这个值就能得到dp[u][0]的最小值

G:大白书上有这题,先对火做一个BFS计算出每个点的蔓延时间,然后利用这个时间,在对人做一个BFS,注意这题有个坑点,就是如果人走到出口就直接出去了,因为岩浆是后蔓延到的

H:贪心,对于y操作,最好的肯定是把后面的1放到前面的0的位置,那么就是要找一个临界值,后面放X个1,其余都使用x操作一步步挪到前面,这个直接枚举,然后维护一些前缀和七七八八的东西。写起来还是要注意细节,具体见代码

代码:

A:

#include <cstdio>
#include <cstring>
#include <stack>
using namespace std;

typedef long long ll;
const int N = 2005;
int n, m;
char str[N];
int g[N][N];
stack<pair<int, int> > S;

ll get(int s, int k) {
    return (ll)(2 * s - (k - 1)) * k / 2;
}

int main() {
    while (~scanf("%d%d", &n, &m)) {
        for (int i = 0; i < n; i++) {
            scanf("%s", str);
            for (int j = 0; j < m; j++) {
                if (str[j] == 'b') g[i][j] = 0;
                else g[i][j] = 1;
            }
        }
        for (int i = 0; i < m; i++) {
            int pre = n;
            for (int j = n - 1; j >= 0; j--) {
                if (g[j][i] == 0) pre = j;
                g[j][i] = pre;
            }
        }
        for (int i = 0; i < n; i++) g[i][m] = i;
        ll ans = 0;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j <= m; j++) {
                int h = g[i][j] - i, v = j, pre = j;
                while (!S.empty() && S.top().first > h) {
                    v = S.top().second;
                    ans += get(j - v, pre - v) * (S.top().first - h);
                    pre = v;
                    S.pop();
                }
                if (h) S.push(make_pair(h, v));
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

B:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long ll;

ll a, b;
ll ans;

int main() {
    while (~scanf("%I64d%I64d", &a, &b)) {
        ans = 0;
        for (ll i = 1; i * i * i <= b; i++) {
            ll sb = max(a, i * i * i);
            ans += b / (i * i) - (sb - 1) / (i * i);
        }
        printf("%I64d\n", ans);
    }
    return 0;
}

C:

#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;

const int MAXN = 400005;
const int N = 100000;
const int M = 100000;
int n, m, q;

int parent[MAXN];

int find(int x) {
    if (x == parent[x])return x;
    return parent[x] = find(parent[x]);
}

void uni(int a, int b) {
    int pa = find(a);
    int pb = find(b);
    if (pb < pa) swap(pb, pa);
    if (pa != pb) parent[pa] = pb;
}

int main() {
    while (~scanf("%d%d%d", &n, &m, &q)) {
        int a, b, c;
        for (int i = 0; i < MAXN; i++)
            parent[i] = i;
        for (int i = 1; i <= n; i++) {
            scanf("%d%d", &a, &b);
            a--; b--;
            if (b != -1) {
                uni(a, b + N + M);
            }
        }
        for (int i = 1; i <= m; i++) {
            scanf("%d%d%d", &a, &b, &c);
            a--; b--; c--;
            uni(a + N, b);
            if (c != -1) {
                uni(a + N, c + N + M);
                uni(b, c + N + M);
            }
        }
        int tp,id;
        while (q--) {
            scanf("%d%d", &tp, &id);
            id--;
            if (tp == 1) id += N;
            int x = find(id);
            if (x >= N + M) printf("%d\n", x - (N + M) + 1);
            else printf("0\n");
        }
    }
    return 0;
}

D:

#include <cstdio>
#include <cstring>

int t;
char n[105];

typedef long long ll;

ll gcd(ll a, ll b) {
    if (!b) return a;
    return gcd(b, a % b);
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%s", &n);
        int len = strlen(n);
        ll sb = 0, fuck = 1;
        for (int i = 0; i < len; i++) {
            if (n[i] == '.') {
                for (int j = i + 1; j < len; j++) {
                    sb = sb * 10 + n[j] - '0';
                    fuck *= 10;
                }
                break;
            }
            sb = sb * 10 + n[i] - '0';
        }

        ll d = gcd(sb, fuck);
        printf("%I64d/%I64d\n", sb / d, fuck / d);
    }
    return 0;
}

E:

#include <cstdio>
#include <cstring>
#include <set>
#include <vector>
#include <algorithm>
using namespace std;

typedef long long ll;
const int N = 50005;
int n, col[N];
vector<int> g[N];

struct Point {
    int x, y;
    void read() {
        scanf("%d%d", &x, &y);
    }
} p[N];

bool cmpx(Point a, Point b) {
    return a.x < b.x;
}

int w[2], ans;

bool dfs(int u) {
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        if (col[u] == col[v]) return false;
        if (col[v] == -1) {
            col[v] = !col[u];
            w[col[v]]++;
            dfs(v);
        }
    }
    return true;
}

ll dis(Point a, Point b) {
    ll dx = a.x - b.x;
    ll dy = a.y - b.y;
    return dx * dx + dy * dy;
}

int main() {
    while (~scanf("%d", &n)) {
        for (int i = 0; i < n; i++) {
            p[i].read();
            g[i].clear();
            col[i] = -1;
        }
        sort(p, p + n, cmpx);
        for (int i = 0; i < n; i++) {
            for (int j = i + 1; p[j].x - p[i].x <= 5; j++) {
                if (dis(p[j], p[i]) <= 25LL) {
                    g[i].push_back(j);
                    g[j].push_back(i);
                }
            }
        }
        int flag = 0;
        ans = 0;
        for (int i = 0; i < n; i++) {
            if (col[i] == -1) {
                col[i] = 0;
                w[0] = 1; w[1] = 0;
                if (!dfs(i)) {
                    flag = 1;
                    break;
                }
                ans += max(w[0], w[1]);
            }
        }
        if (flag) printf("-1\n");
        else printf("%d\n", ans);
    }
    return 0;
}

F:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
using namespace std;

const int N = 100005;
int n;
const int INF = 0x3f3f3f3f;
int cost[N], vis[N], dp[N][2];
vector<int> g[N];

void dfs(int u) {
    dp[u][0] = dp[u][1] = 0;
    if (g[u].size() == 0)
        return;
    int Min = -INF, Minv;
    for (int i = 0; i < g[u].size(); i++) {
        int v = g[u][i];
        dfs(v);
        if (Min < dp[v][1] - dp[v][0] + cost[v]) {
            Min = dp[v][1] - dp[v][0] + cost[v];
            Minv = v;
        }
        dp[u][1] += dp[v][1] + cost[v];
    }
    dp[u][0] = dp[u][1] - dp[Minv][1] - cost[Minv] + dp[Minv][0];
}

int main() {
    while (~scanf("%d", &n)) {
        int u, v, w;
        for (int i = 1; i <= n; i++) {
            vis[i] = 0;
            g[i].clear();
        }
        for (int i = 0; i < n - 1; i++) {
            scanf("%d%d%d", &u, &v, &w);
            g[u].push_back(v);
            cost[v] = w;
        }
        dfs(1);
        printf("%d\n", dp[1][0]);
    }
    return 0;
}

G:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int N = 1005;
const int INF = 0x3f3f3f3f;
char g[N][N];
int t, n, m;

struct Point {
    int x, y;
    Point() {}
    Point(int x, int y){
        this->x = x;
        this->y = y;
    }
} s, e;

const int d[4][2] = {0, 1, 0, -1, 1, 0, -1, 0};

int bid[N][N], vis[N][N];

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%d%d", &n, &m);
        queue<Point> Q;
        for (int i = 0; i < n; i++) {
            scanf("%s", g[i]);
            for (int j = 0; j < m; j++) {
                bid[i][j] = INF;
                vis[i][j] = INF;
                if (g[i][j] == 'S') {
                    s.x = i;
                    s.y = j;
                }
                if (g[i][j] == '!') {
                    Q.push(Point(i, j));
                    bid[i][j] = 0;
                }
                if (g[i][j] == 'E') {
                    e.x = i;
                    e.y = j;
                }
            }
        }
        while (!Q.empty()) {
            Point u = Q.front(); Q.pop();
            for (int i = 0; i < 4; i++) {
                Point v;
                v.x = u.x + d[i][0];
                v.y = u.y + d[i][1];
                if (v.x < 0 || v.x >= n || v.y < 0 || v.y >= m || g[v.x][v.y] == '#') continue;
                if (bid[v.x][v.y] > bid[u.x][u.y] + 1) {
                    bid[v.x][v.y] = bid[u.x][u.y] + 1;
                    Q.push(v);
                }
            }
        }
        Q.push(s);
        vis[s.x][s.y] = 0;
        int flag = 0;
        while (!Q.empty()) {
            Point u = Q.front(); Q.pop();
            for (int i = 0; i < 4; i++) {
                Point v;
                v.x = u.x + d[i][0];
                v.y = u.y + d[i][1];
                if (v.x < 0 || v.x >= n || v.y < 0 || v.y >= m || g[v.x][v.y] == '#') continue;
                if (v.x == e.x && v.y == e.y && bid[v.x][v.y] >= vis[u.x][u.y] + 1) {
                    flag = 1;
                    break;
                }
                if (bid[v.x][v.y] <= vis[u.x][u.y] + 1) continue;
                if (vis[v.x][v.y] > vis[u.x][u.y] + 1) {
                    vis[v.x][v.y] = vis[u.x][u.y] + 1;
                    Q.push(v);
                }
            }
        }
        printf("%s\n", flag ? "Yes" : "No");
    }
    return 0;
}

H:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

const int N = 100005;

typedef long long ll;
int t, n;
char str[N];
ll x, y;
int one[N], zero[N], on, zn;
ll sum[N], bit[N];

inline int lowbit(int x){
    return x&(-x);
}

void add(int x, int v) {
    while (x <= n) {
        bit[x] += v;
        x += lowbit(x);
    }
}

ll get(int x) {
    ll ans = 0;
    while (x) {
        ans += bit[x];
        x -= lowbit(x);
    }
    return ans;
}

int main() {
    scanf("%d", &t);
    while (t--) {
        scanf("%I64d%I64d", &x, &y);
        scanf("%s", str + 1);
        n = strlen(str + 1);
        memset(bit, 0, sizeof(bit));
        on = zn = 0;
        ll tot = 0;
        ll sb = 0;
        for (int i = 1; i <= n; i++) {
            sum[i] = sum[i - 1];
            if (str[i] == '1') {
                tot += sb;
                one[on++] = i;
                sum[i] += 1;
            } else {
                sb++;
                add(i, 1);
            }
        }
        for (int i = n; i >= 1; i--) if (str[i] == '0') zero[zn++] = i;
        ll ans = 0;
        while (on && zn && one[on - 1] > zero[zn - 1]) {
            if (x * tot < y + x * (tot - get(one[on - 1]) - (sum[one[on - 1] - 1] - sum[zero[zn - 1]]))) {
                ans += x * tot;
                break;
            } else {
                tot -= get(one[on - 1]) + (sum[one[on - 1] - 1] - sum[zero[zn - 1]]);
                add(zero[zn - 1], -1);
                zn--; on--;
                ans += y;
            }
        }
        printf("%I64d\n", ans);
    }
    return 0;
}


福州大学第十二届程序设计竞赛题解

标签:

原文地址:http://blog.csdn.net/accelerator_/article/details/45468987

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!