Codeforces Round #353 (Div. 2)

 

数学 A - Infinite Sequence

等差数列,公差是0的时候特判

#include <bits/stdc++.h>

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

int main() {
    int a, b, c;
    scanf ("%d%d%d", &a, &b, &c);
    bool flag = true;
    if (c == 0) {
        if (a == b) {
            flag = true;
        } else {
            flag = false;
        }
    } else {
        int d = (b - a) / c;
        if (d >= 0 && (b - a) % c == 0) {
            flag = true;
        } else {
            flag = false;
        }
    }
    if (flag) {
        puts ("YES");
    } else {
        puts ("NO");
    }
    return 0;
}

数学 B - Restoring Painting

题意:3*3的矩阵,已经填了a,b,c,d四个数字,问填完数后四个2*2的子矩阵的和相等的方案数,所有数字范围在[1, n].

分析:蛮有意思的题目,很明显中心的数字是公有的,?从上到下从左到右设为x1,x2,x3,x4x5,那么满足x1+a+b=x4+b+d -> x4 = x1 + (a  - d),x2=x1+(b-c), x5=x1+(a+b-c-d),因为x2, x4, x5范围在[1, n],能得到一个x1的最小可行区间,然后*x3的可行区间(n).当然O(n)枚举也可以.

#include <bits/stdc++.h>

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

int main() {
    int n, a, b, c, d;
    scanf ("%d%d%d%d%d", &n, &a, &b, &c, &d);
    int d1 = a - d, d2 = b - c, d3 = a + b - c - d;
    int l = 1, r = n;
    l = std::max (l, 1 - d1);
    r = std::min (r, n - d1);

    l = std::max (l, 1 - d2);
    r = std::min (r, n - d2);

    l = std::max (l, 1 - d3);
    r = std::min (r, n - d3);
    if (l <= r) {
        long long ans = 1ll * (r - l + 1) * n;
        std::cout << ans << '\n';
    } else {
        puts ("0");
    }
    return 0;
}

数学 C - Money Transfers

题意:n个数字有正有负,总和0,相邻数字可以分配,问最小操作数使得所有数字变成0.

分析:如果一段长度为L数字总和为0,最多L-1次可以使得每个数字为0.将n个数字分成m段都是0的,那么答案是n-m,所以求cnt[k]最大,表示m最大(最后一组为-k+k).

#include <bits/stdc++.h>

int main() {
	std::ios::sync_with_stdio (false);
	std::cin.tie (0);
	std::map<long long, int> mp;
	int n;
	std::cin >> n;
	long long sum = 0;
	int mx = 0;
	for (int i=0; i<n; ++i) {
		int x;
		std::cin >> x;
		sum += x;
		mp[sum]++;
		mx = std::max (mx, mp[sum]);
	}
	std::cout << n - mx << '\n';
	return 0;
}

set D - Tree Construction

题意:按照BST建一棵树二叉树,问当前插入的点的父节点.

分析:set模拟平衡树,lower_bound查找位置.

#include <bits/stdc++.h>

const int N = 1e5 + 5;
std::set<int> st;
std::map<int, int> left, right;

int main() {
    int n, x;
    scanf ("%d", &n);
    scanf ("%d", &x);
    st.insert (x);
    int ans;
    for (int i=0; i<n-1; ++i) {
        scanf ("%d", &x);
        auto it = st.lower_bound (x);
        if (it != st.end () && left.count (*it) == 0) {
            left[*it] = x;
            ans = *it;
        } else {
            --it;
            right[*it] = x;
            ans = *it;
        }
        st.insert (x);
        printf ("%d ", ans);
    }

    return 0;
}

DP E - Trains and Statistic

题意:第i个车站能到[i+1, a[i]]的位置,p(i, j)表示从i到j最少搭几次车.求

分析:定义dp[i]表示的最小搭车数,从[i+1, n]中a[m]最大的dp[m]转移来,...

#include <bits/stdc++.h>

const int N = 1e5 + 5;
int a[N];
long long dp[N];
std::pair<int, int> mx[N][20];
int n;

void init_ST() {
    for (int i=0; i<n; ++i) {
        mx[i][0] = {a[i], i};
    }
    for (int j=1; (1<<j)<=n; ++j) {
        for (int i=0; i+(1<<j)-1<n; ++i) {
            mx[i][j] = std::max (mx[i][j-1], mx[i+(1<<(j-1))][j-1]);
        }
    }
}

int query_max(int l, int r) {
    int k = 0; while (1<<(k+1) <= r - l + 1) k++;
    return std::max (mx[l][k], mx[r-(1<<k)+1][k]).second;
}

int main() {
    scanf ("%d", &n);
    a[n-1] = n - 1;
    for (int i=0; i<n-1; ++i) {
        scanf ("%d", a+i);
        a[i]--;
    }
    init_ST ();
    long long ans = 0;
    dp[n-1] = 0;
    for (int i=n-2; i>=0; --i) {
        int p = query_max (i + 1, a[i]);
        dp[i] = dp[p] - (a[i] - p) + n - i - 1;
        ans += dp[i];
    }
    printf ("%I64d\n", ans);
    return 0;
}

  

 

posted @ 2016-05-18 16:27  Running_Time  阅读(162)  评论(0编辑  收藏  举报