StkOvflow

STACK OVERFLOW!

一言(ヒトコト)


我要女装!
——zzx

AcWing362. 区间

题目描述

给定 n 个区间 [ai,bi]n 个整数 ci

你需要构造一个整数集合 Z,使得 i[1,n]Z 中满足 aixbi 的整数 x 不少于 ci 个。

求这样的整数集合 Z 最少包含多少个数。

解题思路

根据前缀和思想,我们用s[k]表示最好选法中,整数集合Z包含了0k中的s[k]个数,那在整数集合中aixbi的数也就是s[bi]s[ai1]ci,那我们就可以看出一个差分约束系统,将ai1bi连一条权重为1的有向边。

但是如果要求解,那这一个差分约束的条件不够,应该再找几个:

a.由于0k中间选的数不会0k1的少,所以s[k]s[k1]0

b.由于一个数至多只能选一次,所以s[k]s[k1]1,转化成s[k1]s[k]1

整理上式我们可以得到一个差分约束系统

{s[bi]s[ai1]cis[k]s[k1]0s[k1]s[k]1

然后就是求一个150001的最长路,为了方便可以把所有下标+1

代码

#include <iostream>
#include <cstring>

using namespace std;

const int N = 5e4 + 10, M = 3 * N;
int dist[M], st[M], q[M], hh = 0, tt = 1;
int h[M], e[M], ne[M], w[M], idx;
int n, a, b, c;

int spfa() 
{
    memset(dist, 0xcf, sizeof dist);
    
    q[0] = dist[0] = 0, st[0] = true;
    
    while (hh != tt) 
    {
        int t = q[hh ++ ];
        st[t] = 0;
        if (hh == N) hh = 0;
        
        for (int i = h[t]; ~i; i = ne[i]) 
        {
            int j = e[i];
            if (dist[j] < dist[t] + w[i]) 
            {
                dist[j] = dist[t] + w[i];
                if (!st[j]) 
                {
                    q[tt ++ ] = j, st[j] = 1;
                    if (tt == N) tt = 0;
                }
            }
        }
    }
    
    return dist[50001];
}

void add(int a, int b, int c) 
{
    e[idx] = b, ne[idx] = h[a], w[idx] = c, h[a] = idx ++ ;
}

int main() 
{
    scanf("%d", &n);
    
    memset(h, -1, sizeof h);
    for (int i = 1; i <= 50001; i ++ ) 
        add(i - 1, i, 0), add(i, i - 1, -1);
        
    for (int i = 1; i <= n; i ++ ) 
    {
        scanf("%d%d%d", &a, &b, &c);
        add(a, b + 1, c);
    }
    
    printf("%d\n", spfa());
    
    return 0;
}
posted @   StkOvflow  阅读(35)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示