dp cf 20190615

A. Timofey and a tree

这个不算是dp,就是一个思维题,好难想的思维题,看了题解才写出来的,

把点和边分开,如果一条边的两个点颜色不同就是特殊边,特殊边两边连的点就叫特殊点,

如果一个点的被计算的次数等于特殊边的次数,则说明它是我们所求的点

#include <cstdio>
#include <cstdlib>
#include <queue>
#include <vector>
#include <cstring>
#include <algorithm>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int maxn = 1e5 + 10;
int num[maxn], a[maxn];
pair<int, int>pii[maxn];

int main()
{
    int n;
    scanf("%d", &n);
    for(int i=1;i<n;i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        pii[i] = make_pair(u, v);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
    for(int i=1;i<n;i++)
    {
        int u = pii[i].first, v = pii[i].second;
        if(a[u]!=a[v])
        {
            num[u]++;
            num[v]++;
            ans++;
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(num[i]==ans)
        {
            printf("YES
");
            printf("%d
",i);
            return 0;
        }
    }
    printf("NO
");
    return 0;
}
A

 A. Chain Reaction

这个我觉得挺难的。。。。

网上题解,dp[i]来表示激活第i个位置,从前面往后推到第i个位置,这个塔存留下来的数量。

这个是线性的,后面那个位置都是由前面的那个位置推过来的,如果我们选了后面那个位置,如果后面的无法把前面的那个位置炸掉

那么只能不炸,或者由最后添加的那个点来炸掉之前你需要炸掉的区间。

这个题目简单,是因为可以转化成线性的,不过我觉得好难想。

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <queue>
#include <vector>
#include <algorithm>
#define inf 0x3ff3f3f
using namespace std;
const int maxn = 1e6 + 10;
int d[maxn], dp[maxn];
int main()
{
    int n;
    scanf("%d", &n);
    int mm = 0;
    for(int i=1;i<=n;i++)
    {
        int a;
        scanf("%d", &a);
        scanf("%d", &d[a]);
        mm = max(mm, a);
    }
    if (d[0]) dp[0] = 1;
    int res = min(n, n - dp[0]);
    for(int i=1;i<=mm;i++)
    {
        if (d[i] == 0) dp[i] = dp[i - 1];
        else {
            if (d[i] >= i) dp[i] = 1;
            else {
                dp[i] = dp[i - 1 - d[i]] + 1;
            }
        }
        res = min(res, n - dp[i]);
    }
    printf("%d
", res);
    return 0;
}
A
原文地址:https://www.cnblogs.com/EchoZQN/p/11026591.html