Codeforces Round #345 (Div. 2)

DFS A - Joysticks

嫌麻烦直接DFS暴搜吧,有坑点是当前电量<=1就不能再掉电,直接结束。

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
int ans = 0;

void DFS(int a, int b, int step) {
    if (a <= 0 || b <= 0) {
        ans = std::max (ans, step); return ;
    }
    if (a < b && b - 2 >= 0) {
        DFS (a + 1, b - 2, step + 1);
    } else if (a >= b && a - 2 >= 0) {
        DFS (a - 2, b + 1, step + 1);
    }
}

int main() {
    int a, b;   std::cin >> a >> b;
    ans = 0;
    DFS (a, b, 0);
    std::cout << ans << '\n';

    return 0;
}

构造 + 贪心 B - Beautiful Paintings

每次取出不重复的递增序列,直到集合为空

#include <bits/stdc++.h>

typedef long long ll;
const int N = 1e5 + 5;
std::vector<int> vec;

int main() {
    int n;  std::cin >> n;
    for (int x, i=0; i<n; ++i) {
        std::cin >> x; vec.push_back (x);
    }
    std::sort (vec.begin (), vec.end ());
    int ans = 0;
    while (vec.size () > 0) {
        std::vector<int> tmp;
        int pre = 0, num = 0;
        for (auto x: vec) {
            if (x > pre) {
                num++; pre = x;
            } else {
                tmp.push_back (x);
            }
        }
        ans += num - 1; vec = tmp;
    }
    std::cout << ans << '\n';

    return 0;
}

数学 + 容斥 C - Watchmen

化简公式得到找到pair (i, j) xi == xj || yi == yj。找两次再容斥一下。map做更好。

#include <bits/stdc++.h>

typedef long long ll;
const int N = 2e5 + 5;
const int INF = 1e9 + 7;
std::pair<int, int> point[N];

ll calc(int n) {
    return 1ll * n * (n - 1) / 2;
}

bool cmpx(std::pair<int, int> a, std::pair<int, int> b) {
    return a.first < b.first;
}

bool cmpy(std::pair<int, int> a, std::pair<int, int> b) {
    return a.second < b.second;
}
int main() {
    int n; scanf ("%d", &n);
    for (int x, y, i=0; i<n; ++i) {
        scanf ("%d%d", &x, &y);
        point[i] = std::make_pair (x, y);
    }
    std::sort (point, point+n, cmpx);
    ll ans = 0;
    int x = INF, y = INF, num = 1;
    for (int i=0; i<n; ++i) {
        if (x == point[i].first) {
            num++;
        } else {
            x = point[i].first;
            if (num > 1) {
                ans += calc (num);
            }
            num = 1;
        }
    }
    if (num > 1) {
        ans += calc (num);
    }
    std::sort (point, point+n, cmpy);
    x = INF; y = INF; num = 1;
    for (int i=0; i<n; ++i) {
        if (y == point[i].second) {
            num++;
        } else {
            y = point[i].second;
            if (num > 1) {
                ans += calc (num);
            }
            num = 1;
        }
    }
    if (num > 1) {
        ans += calc (num);
    }
    std::sort (point, point+n);
    x = INF; y = INF; num = 1;
    for (int i=0; i<n; ++i) {
        if (x == point[i].first && y == point[i].second) {
            num++;
        } else {
            x = point[i].first, y = point[i].second;
            if (num > 1) {
                ans -= calc (num);
            }
            num = 1;
        }
    }
    if (num > 1) {
        ans -= calc (num);
    }
    printf ("%I64d\n", ans);

    return 0;
}

two points D - Image Preview

题意:浏览图片,浏览,滑动以及反转需要时间,问在T时间内最多浏览多少图片。

分析:定义两个指针from,to,可行的方案是n+1->from,from->n+1,n+1->to或者n+1->to,to->n+1,n+1->from,还有from->to。前两个重复滑动的可以选择距离小的,第三个只要定义to=n+1就对了。其实可以用二分做的。

#include <bits/stdc++.h>

typedef long long ll;
const int N = 5e5 + 5;
char str[2*N];
ll tim[2*N];
int n, a, b, T;

ll get_time(int from, int to) {
    ll ret = tim[from] - tim[to-1];
    int move = from - to + std::min (from-(n+1), (n+1)-to);
    return ret + 1ll * a * move;
}

int main() {
    scanf ("%d%d%d%d", &n, &a, &b, &T);
    scanf ("%s", str + 1);
    for (int i=1; i<=n; ++i) {
        tim[i] = (str[i] == 'w' ? (b+1) : 1);
    }
    for (int i=n+1; i<=2*n; ++i) {
        tim[i] = tim[i-n];
    }
    for (int i=1; i<=2*n; ++i) {
        tim[i] += tim[i-1];
    }
    int ans = 0;
    int from = n + 1;
    for (int to=2; to<=n+1; ++to) {
        while (from < to+n-1 && get_time (from+1, to) <= T) from++;
        if (get_time (from, to) <= T) ans = std::max (ans, from - to + 1);
    }
    printf ("%d\n", ans);

    return 0;
}

图论 + 并查集 E - Table Compression

题意:给一个矩阵,求新的矩阵,使得原矩阵的同行,同列的大小关系不变,且使得新矩阵的最大值最小。即离散化

分析:找好顺序,一个一个从小到大填充就行了。因为有相同数字的存在,使用并查集使得将相同的数字赋值离散化后相同的数字。因为有行和列共同影响一个数字,所以建立一个大数到小数的图,类似树形DP,选择当前行或列的最大值+1为离散化后的数字

#include <bits/stdc++.h>

const int N = 1e6 + 5;
std::pair<int, std::pair<int, int> > A[N];
int val[N], ans[N];
int mr[N], mc[N];
int rt[N];
std::vector<int> edge[N];
std::vector<int> num[N];

int Find(int x) {
    return rt[x] == x ? x : rt[x] = Find (rt[x]);
}

int main() {
    int n, m; scanf ("%d%d", &n, &m);
    int tot = n * m;
    for (int i=0; i<n; ++i) {
        for (int j=0; j<m; ++j) {
            scanf ("%d", &val[i*m+j]);
            A[i*m+j].first = val[i*m+j];
            A[i*m+j].second = std::make_pair (i, j);
            rt[i*m+j] = i * m + j;
        }
    }
    std::fill (mr, mr+n, -1);
    std::fill (mc, mc+m, -1);
    std::sort (A, A+tot);
    for (int i=0; i<tot; ++i) {
        int r = A[i].second.first, c = A[i].second.second;
        int pos = r * m + c;
        if (mr[r] != -1) {
            if (val[mr[r]] == A[i].first) {
                rt[pos] = Find (mr[r]);
            } else {
                edge[pos].push_back (mr[r]);
            }
        }
        if (mc[c] != -1) {
            if (val[mc[c]] == A[i].first) {
                rt[Find (pos)] = Find (mc[c]);
            } else {
                edge[pos].push_back (mc[c]);
            }
        }
        mr[r] = mc[c] = pos;
    }
    for (int i=0; i<tot; ++i) {
        num[Find (i)].push_back (i);
    }
    for (int i=0; i<tot; ++i) {
        int r = A[i].second.first, c = A[i].second.second;
        int id = r * m + c;
        if (Find (id) == id) {
            int _max = 0;
            for (auto u: num[id]) {
                for (auto v: edge[u]) {
                    _max = std::max (_max, ans[v]);
                }
            }
            for (auto u: num[id]) {
                ans[u] = _max + 1;
            }
        }
    }
    for (int i=0; i<n; ++i) {
        for (int j=0; j<m; ++j) {
            printf ("%d ", ans[i*m+j]);
        }
        puts ("");
    }

    return 0;
}

  

 

posted @ 2016-03-09 14:42  Running_Time  阅读(250)  评论(0编辑  收藏  举报