补题记录
The 2025 ICPC Asia East Continent Online Contest (I)
C. Canvas Painting
题意:
有1-n个点,每个点的颜色为1-n,给m个线段,对于每个线段[l,r]你可以在区间内选两个点,把一个点的颜色变为另外一个点的颜色。其中n<=1e9, m<=2e5。
思路:
考虑贪心的做法,我们枚举从1到n枚举左端点,设当前左端点为i,把当前左端点对应的右端点加入小根堆,每次取最小的右端点即可。但是n很大,需要离散化处理,注意一下。
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline void solve(){
int m, n; cin >> m >> n;
vector<pair<int, int>> a(m);
vector<int> b;
for(auto &[x, y] : a) {
cin >> x >> y;
b.push_back(x);
b.push_back(y);
}
sort(b.begin(), b.end());
b.erase(unique(b.begin(), b.end()), b.end());
int ans = n;
n = b.size();
auto get = [&](int x) -> int {
return lower_bound(b.begin(), b.end(), x) - b.begin();
};
vector<vector<int>> xl(n);
for(auto [x, y] : a) {
xl[get(x)].push_back(get(y));
}
int l = 0;
priority_queue<int, vector<int>, greater<>> q;
for(int i = 0; i < n - 1; ++i) {
int l = b[i] + 1, r = b[i + 1];
for(auto x : xl[i]) {
q.push(x);
}
while(!q.empty() && q.top() == i) {
q.pop();
}
while(q.size() && l <= r) {
q.pop();
ans--;
++l;
}
}
cout << ans << '\n';
}
signed main() {
cin.tie(0), cout.tie(0) ;
ios::sync_with_stdio(false) ;
int t = 1;
cin >> t ;
while(t -- ) solve() ;
return 0;
}
/*
8
1 3 7 5 2 8 4 6
1 2
1 3
1 4
3 5
5 6
3 7
7 8
*/
D. Min-Max Tree
题意:
n个点构成一颗无根树,每个点有一个权值 a i a_i ai,我们断掉一些边,形成若干个联通块,求联通块的极差的和的最大值。n<=1e6, 0<= a i a_i ai<=1e9
思路:
我们把这个过程视为给每个点赋上一个系数,分别为(1,-1,0)。显然一颗子树中1和-1个数差值的绝对值不会超过1,即最多会有一个1或-1等待匹配,不可能出现两个或更多个1或-1等待匹配。我们定义zero为平衡态,positive为等待匹配-1,negative为等待匹配1。对于一个节点u,有多种转移方式,对于 d p [ u ] [ z e r o ] dp[u][zero] dp[u][zero] ,可以由它自身为0,然后他的儿子能够平衡(注意到要么是所有儿子的子树平衡,或者任意两个儿子的子树满足一个positive一个negative,即不会出现多组+1,-1的匹配)… 转移方式非常多,详细看代码。
#include<bits/stdc++.h>
using namespace std;
#define int long long
inline void solve(){
int n; cin >> n;
vector<int> a(n + 1);
for(int i = 1; i <= n; ++i) cin >> a[i];
if(n == 1) {
cout << "0\n"; return;
}
vector<vector<int>> adj(n + 1);
for(int i = 1; i < n; ++i) {
int u, v; cin >> u >> v;
adj[u].push_back(v)


1643

被折叠的 条评论
为什么被折叠?



