康复计划 Round 2: Codeforces Lyft Level 5 Challenge 2018 - Final Round (Open Div. 1)

题目链接


Codeforces - 1074A T h e T o w e r i s G o i n g H o m e The Tower is Going Home TheTowerisGoingHome

简单说下题意,就是战车一开始是在左下角,战车可以水平走和垂直走,然后有垂直的和水平的障碍,战车可以把他移掉,问战车能够到达纵坐标 1 e 9 1e9 1e9 处最少需要移掉多少障碍。

离散化 + 区间覆盖,首先思考一下,当在右边有更优解的时候,左边这一块间隔肯定不移掉障碍物,到达右边间隔再移掉夹在中间的垂直障碍物,可以看到,我们就可以不用管那些在纵坐标之下的障碍物,那么这个地方就可以对 水 平 障 碍 物 的 左 端 点 , 纵 坐 标 水平障碍物的左端点,纵坐标 进行排序,这样排之后那些纵坐标比前面一个小的就可以丢弃,剩下的就进行区间覆盖,因为坐标很大,所以要离散化。

最后答案就是区间覆盖的最小值,当然还要加上向右走移掉的障碍物。

代码:

#include <bits/stdc++.h>
#pragma GCC optimize "-O3"
#define mst(a,b) memset(a,b,sizeof(a))
#define ALL(x) x.begin(),x.end()
#define pii pair<int,int>
#define eps 1e-6
#define debug(a) cout << #a": " << a << endl;
#define eularMod(a, b) a < b ? a : a % b + b
inline int lowbit(int x){ return x & -x; }
const int N = 1e5 + 10;
const int mod = (int) 998244353;
const int INF = 0x3f3f3f3f;
const long long LINF = (1LL << 62);
typedef long long LL;
typedef unsigned long long ULL;
const double PI = acos(-1.0);
using namespace std;

int n, m, a[N], v[N];
struct line {
    int L, R, Y;
    bool operator < (const line &t) const {
        if (L != t.L) return L < t.L;
        else return Y < t.Y;
    }
}l[N];

int main() {
#ifdef LOCAL
    freopen("in.txt", "r", stdin);
//    freopen("out.txt","w",stdout);
#endif
    scanf("%d%d", &n, &m);

    for (int i = 1; i <= n; i++) {
        scanf("%d", &a[i]);
    }
    a[++n] = 1000000000;
    sort(a + 1, a + 1 + n);

    for (int i = 1; i <= m; i++) {
        scanf("%d%d%d", &l[i].L, &l[i].R, &l[i].Y);
        l[i].L--;
    }
    sort(l + 1, l + m + 1);

    int pre = 0;
    for (int i = 1; i <= m; i++) {
        if (l[i].Y < pre) break;
        pre = l[i].Y;
        int pos1 = lower_bound(a, a + 1 + n, l[i].L) - a;
        int pos2 = lower_bound(a, a + 1 + n, l[i].R) - a;
        if (a[pos2] != l[i].R) pos2--;
        if (pos1 == pos2 || pos1 > pos2) continue;
        v[pos1]++;
        v[pos2]--;
    }

    int ans = INF;
    int tmp = 0;
    int sum = 0;

    for (int i = 0; i < n; i++) {
        sum += v[i];
        ans = min(ans, sum + tmp);
        tmp++;
    }

    printf("%d\n", ans);
    return 0;
}

Codeforces - 1074B I n t e r s e c t i n g S u b t r e e s Intersecting Subtrees IntersectingSubtrees

解释一下官方题解,首先从 L 的子树任选一个结点,询问一次得到同位置自己的结点编号 x

(1)然后再以这个编号 x 作为树根 dfs or bfs 整棵树,找到一个自己子树的结点 y 就记录下来,然后再
(2)询问这个节点在 L 的树上的位置。

为什么这样做呢,首先两棵树结构相同,那么(1)操作找到的自己的结点 y ,是有可能和 x 是在同一棵子树上的(因为他们之间连着一条简单路径),那么就询问这个结点在 L 树上的位置是否是 L 的子树上的结点就 ok, 如果是,这个结点就必然是自己子树和 L 子树的公共结点。

交互题很 newbie (:з)∠)

代码:

#include <bits/stdc++.h>
#pragma GCC optimize "-O3"
#define mst(a,b) memset(a,b,sizeof(a))
#define ALL(x) x.begin(),x.end()
#define pii pair<int,int>
#define eps 1e-6
#define debug(a) cout << #a": " << a << endl;
#define eularMod(a, b) a < b ? a : a % b + b
inline int lowbit(int x){ return x & -x; }
const int N = 1e5 + 10;
const int mod = (int) 998244353;
const int INF = 0x3f3f3f3f;
const long long LINF = (1LL << 62);
typedef long long LL;
typedef unsigned long long ULL;
const double PI = acos(-1.0);
using namespace std;

int n, head[N], cnt, tag;
bool a[N], b[N];
struct Edge {
    int to, nex;
}edge[N << 1];

inline void AddEdge (int u, int v) {
    edge[++cnt].nex = head[u];
    edge[cnt].to = v;
    head[u] = cnt;
    edge[++cnt].nex = head[v];
    edge[cnt].to = u;
    head[v] = cnt;
}
void dfs (int u, int fa) {
    if (a[u]) {
        tag = u;
        return ;
    }
    for (int i = head[u]; i; i = edge[i].nex) {
        int v = edge[i].to;
        if (v != fa) {
            dfs(v, u);
        }
    }
}

int main() {
#ifdef purple_bro
    freopen("in.txt", "r", stdin);
//    freopen("out.txt","w",stdout);
#endif
    int T;
    scanf("%d", &T);

    for (;T--;) {
        mst(head, 0);
        mst(a, false);
        mst(b, false);
        cnt = 0;

        scanf("%d", &n);

        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            AddEdge(u, v);
        }

        int k, tmp;
        scanf("%d", &k);

        for (int i = 1; i <= k; i++) {
            scanf("%d", &tmp);
            a[tmp] = true;
        }

        scanf("%d", &k);

        for (int i = 1; i <= k; i++) {
            scanf("%d", &tmp);
            b[tmp] = true;
        }

        printf("B %d\n", tmp);
        fflush(stdout);
        scanf("%d", &tag);

        dfs(tag, 0);

        printf("A %d\n", tag);
        fflush(stdout);
        scanf("%d", &tmp);

        if (b[tmp]) printf("C %d\n", tag);
        else printf("C -1\n");
        fflush(stdout);
    }

    return 0;
}

Codeforces - 1074C O p t i m a l P o l y g o n P e r i m e t e r Optimal Polygon Perimeter OptimalPolygonPerimeter

很神奇的一道题。首先,一圈下来的哈密顿距离恰好是 2 ∗ ( m a x X − m i n X + m a x Y − m i n Y ) 2 * (maxX - minX + maxY - minY) 2(maxXminX+maxYminY)
所以,大于 4 的直接就是一圈的哈密顿距离,然后 3 的就 O ( n ) O(n) O(n) 枚举求出来

代码:

#include <bits/stdc++.h>
using namespace std;
const int N = 5e5 + 10;
const int INF = 0x3f3f3f3f;
typedef long long LL;

int n, v[N][2];

int main()
{
#ifdef purple_bro
    freopen("in.txt", "r", stdin);
#endif
    scanf("%d", &n);

    int maxX, maxY, minX, minY;

    maxX = -INF;
    maxY = -INF;
    minX = INF;
    minY = INF;


    for (int i = 1; i <= n; i++) {
        scanf("%d%d", &v[i][0], &v[i][1]);
        maxX = max(maxX, v[i][0]);
        minX = min(minX, v[i][0]);
        maxY = max(maxY, v[i][1]);
        minY = min(minY, v[i][1]);
    }

    int ans = 0;

    for (int i = 1; i <= n; i++) {
        ans = max(ans, abs(maxX - v[i][0]) + abs(minY - v[i][1]));
        ans = max(ans, abs(maxX - v[i][0]) + abs(maxY - v[i][1]));
        ans = max(ans, abs(minX - v[i][0]) + abs(minY - v[i][1]));
        ans = max(ans, abs(minX - v[i][0]) + abs(maxY - v[i][1]));
    }

    printf("%d ", ans * 2);

    for (int i = 4; i <= n; i++) {
        printf("%d ", 2 * (maxX - minX + maxY - minY));
    }
    return 0;
}

Codeforces - 1074D D e d u c t i o n Q u e r i e s Deduction Queries DeductionQueries

就一傻 x x x 带权并查集,只不过数有点大,要用 m a p map map 存。
推荐一篇带权并查集学习 b l o g blog blog

代码:

#include <bits/stdc++.h>
#include <ext/rope>
using namespace __gnu_cxx;
using namespace std;
#define mst(a,b) memset(a,b,sizeof(a))
#define ALL(x) x.begin(),x.end()
#define pii pair<int,int>
#define eps 1e-6
#define debug(a) cout << #a": " << a << endl;
#define eularMod(a, b) a < b ? a : a % b + b
inline int lowbit(int x){ return x & -x; }
const int N = 2e5 + 10;
const int mod = (int) 1e9 + 7;
const int INF = 0x3f3f3f3f;
const long long LINF = (1LL << 62);
typedef long long LL;
typedef unsigned long long ULL;
const double PI = acos(-1.0);

map<int, int> fa, sum;

int get (int x) {
    if (fa.find(x) == fa.end()) return x;
    else {
        int root = get(fa[x]);
        sum[x] ^= sum[fa[x]];
        return fa[x] = root;
    }
}
int getDis (int x) {
    if (fa.find(x) == fa.end()) return 0;
    return sum[x];
}

int main() {
#ifdef purple_bro
    freopen("in.txt", "r", stdin);
//    freopen("out.txt","w",stdout);
#endif
    int n, ans = 0;

    scanf("%d", &n);

    for (;n--;) {
        int op, u, v;
        scanf("%d%d%d", &op, &u, &v);
        u ^= ans;
        v ^= ans;

        if (u > v) swap(u, v);
        u--;

        int du = get(u);
        int dv = get(v);
        if (op == 1) {
            int x;
            scanf("%d", &x);
            x ^= ans;
            if (du != dv) {
                sum[dv] = getDis(u) ^ getDis(v) ^ x;
                fa[dv] = du;
            }
        } else {
            if (du != dv) {
                printf("-1\n");
                ans = 1;
            } else {
                ans = getDis(u) ^ getDis(v);
                printf("%d\n", ans);
            }
        }
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值