补题记录 The 2025 ICPC Asia East Continent Online Contest (I)

补题记录

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值