VP Educational Codeforces Round 10


A. Gabriel and Caterpillar

题意:一个毛毛虫要从xy,每天早上12小时每小时走a米,晚上12小时每小时走b米,求第几天到y

这题读题给我读傻了,题目说一开始是从下午两点开始观察的,我以为它也要到某天的下午两点后到y才能观察到,然后它说毛毛虫可以调到地下再爬上去,我以为是到地下x就是0。。。唐完了。
其实就是个模拟,只要注意一开始的一天只有8小时往上爬,然后特判一下无解的情况就行了。

点击查看代码
void solve() {
    i64 x, y, a, b;
    std::cin >> x >> y >> a >> b;

    if (x + a * 8 >= y) {
		std::cout << 0 << "\n";
		return;
	}


    x = x + a * 8 - b * 12;

    if (x + 12 * a < y && a <= b) {
    	std::cout << -1 << "\n";
    	return;
    }

    int ans = 1;
   	x += 12 * a;
   	while (x < y) {
   		x -= 12 * b;
   		++ ans;
   		x += 12 * a;
   	}

   	std::cout << ans << "\n";
}

B. z-sort

题意:给你一个数组,你要重新排列它,使得偶数位置上的数大于等于左边的数,奇数位置上的数小于等于左边的数。

排序后拿前半部分给奇数位置,后半部分给偶数位置。

点击查看代码
void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::sort(a.begin(), a.end());
    for (int i = 0, j = 0, k = (n + 1) / 2; i < n; ++ i) {
    	if (i & 1) {
    		std::cout << a[k] << " ";
    		k += 1;
    	} else {
    		std::cout << a[j] << " ";
    		j += 1;
    	}
    }
    std::cout << "\n";
}

C. Foe Pairs

题意:给你一个排列,和若干对限制,如果一个区间里有两个数在这些限制里,就不能选,求能选多少区间。

给每个数几下配对的数,然后从前往后枚举,记录每个数上一次出现的地方,那么和当前位置上的数匹配的数出现的位置的最大值就是我们能选的左边界。

点击查看代码
void solve() {
    int n, m;
    std::cin >> n >> m;
    std::vector<int> a(n);
    for (int i = 0; i < n; ++ i) {
    	std::cin >> a[i];
    }

    std::vector<std::set<int>> s(n + 1);
    for (int i = 0; i < m; ++ i) {
    	int x, y;
    	std::cin >> x >> y;
    	s[x].insert(y);
    	s[y].insert(x);
    }

    i64 ans = 0;
    int last = -1;
    std::vector<int> pre(n + 1, -1);
    for (int i = 0; i < n; ++ i) {
    	for (auto & x : s[a[i]]) {
    		last = std::max(last, pre[x]);
    	}

    	ans += i - last;
    	pre[a[i]] = i;
    }

    std::cout << ans << "\n";
}

D. Nested Segments

题意:给n个线段,求每个线段包含几个线段。

先离散化,然后按右端点排序,那么我们按顺序枚举的i它的ri大于等于前面的所有线段,那么只要找有多少左端点大于等于li的线段就行,可以以树状数组维护左端点个数。

点击查看代码
template <class T>
struct Fenwick {
    int n;
    std::vector<T> tr;

    Fenwick(int _n) {
        init(_n);
    }

    void init(int _n) {
        n = _n;
        tr.assign(_n + 1, T{});
    }

    void add(int x, const T &v) {
        for (int i = x; i <= n; i += i & -i) {
            tr[i] = tr[i] + v;
        }
    }

    T query(int x) {
        T res{};
        for (int i = x; i; i -= i & -i) {
            res = res + tr[i];
        }
        return res;
    }

    T sum(int l, int r) {
        return query(r) - query(l - 1);
    }
};

void solve() {
    int n;
    std::cin >> n;
    std::vector<std::array<int, 3>> a(n);
    std::vector<int> b;
    for (int i = 0; i < n; ++ i) {
    	int l, r;
    	std::cin >> l >> r;
    	a[i] = {l, r, i};
    	b.push_back(l);
    	b.push_back(r);
    }

    std::sort(b.begin(), b.end());
    b.erase(std::unique(b.begin(), b.end()), b.end());

    auto get = [&](int x) -> int {
    	return std::lower_bound(b.begin(), b.end(), x) - b.begin() + 1;
    };

    int m = b.size();
    for (auto & [l, r, id] : a) {
    	l = get(l);
    	r = get(r);
    }

    std::sort(a.begin(), a.end(), [&](std::array<int, 3> & a, std::array<int, 3> & b) {
    	return a[1] < b[1];
    });

    std::vector<int> ans(n);
    Fenwick<int> tr(m + 1);
    for (auto & [l, r, id] : a) {
    	ans[id] = tr.sum(l, m);
    	tr.add(l, 1);
    }

    for (int i = 0; i < n; ++ i) {
    	std::cout << ans[i] << "\n";
    }
}

E. Pursuit For Artifacts

题意:给你一个图,边权只有01两种,求ab有没有一条路径上至少有一条边值是1

如果两个点在一个环里,且这个环里有边的边权是1,那么就一定可以拿到这个1,那么只要在一个边联通分量里有至少一条1边,那么这个联通分量任意两个点都有满足的路径,那么考虑缩点,缩点后是一棵树,只需要看ab的唯一路径上有没有联通块有1边或者有没有树边是1边。

点击查看代码
const int N = 3e5 + 5, M = 6e5 + 5;

int head[N], ver[M], next[M], w[M], tot;
int dfn[N], low[N], stk[N], top, id[N], idx, cnt;
std::vector<std::pair<int, int>> adj[N];
int f[N];
int n, m;

void add(int u, int v, int x) {
	ver[tot] = v; w[tot] = x; next[tot] = head[u]; head[u] = tot ++ ;
}

void tarjan(int u, int fa) {
	dfn[u] = low[u] = ++ idx;
	stk[ ++ top] = u;
	for (int i = head[u]; i != -1; i = next[i]) {
		int v = ver[i];
		if (!dfn[v]) {
			tarjan(v, i);
			low[u] = std::min(low[u], low[v]);
		} else if ((i ^ 1) != fa) {
			low[u] = std::min(low[u], dfn[v]);
		}
	}

	if (dfn[u] <= low[u]) {
		int v;
		++ cnt;
		do {
			v = stk[top -- ];
			id[v] = cnt;
		} while (v != u);
	}
}

int a, b;
bool dfs(int u, int s, int fa) {
	s |= f[u];
	if (u == b) {
		return s == 1;
	}

	for (auto & [v, w] : adj[u]) {
		if (v == fa) {
			continue;
		}

		if (dfs(v, s | w, u)) {
			return true;
		}
	}

	return false;
}

void solve() {
    std::cin >> n >> m;
    memset(head, -1, sizeof head);
    for (int i = 0; i < m; ++ i) {
    	int u, v, w;
    	std::cin >> u >> v >> w;
    	add(u, v, w);
    	add(v, u, w);
    }

    std::cin >> a >> b;

    for (int i = 1; i <= n; ++ i) {
    	if (!dfn[i]) {
    		tarjan(i, -1);
    	}
    }

    for (int u = 1; u <= n; ++ u) {
    	for (int i = head[u]; i != -1; i = next[i]) {
    		int v = ver[i];
    		if (id[u] == id[v]) {
    			f[id[u]] |= w[i];
    		} else {
    			adj[id[u]].push_back({id[v], w[i]});
    		}
    	}
    }

    a = id[a], b = id[b];
    if (dfs(a, 0, 0)) {
    	std::cout << "YES\n";
    } else {
    	std::cout << "NO\n";
    }
}
posted @   maburb  阅读(4)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
点击右上角即可分享
微信分享提示