poj 1201 interval 差分约束/贪心+线段树区间更新

poj1201(二分+线段树)或(差分约束系统) 题意:数轴上每个位置为0或是1,给n(1 个区间[ai, bi],每个区间内至少有 ci 个1.0 1 。问数轴上至少有多少个1可以满足要求。 解法1:现将区间按右端点排序,然后每个区间内的点尽量往右边放,这样子可以照顾到以后的。在找每个区间的放法时,线段树查询区间1的个数,二分查找要放的后缀位置,然后将整个区间后缀全部涂上1.总复杂度是nlognlogn。网上没找到有人这么做的,但 阅读详情

Intervals
Time Limit: 2000MS Memory Limit: 65536K
Total Submissions: 22337 Accepted: 8423

Description

You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. 
Write a program that: 
reads the number of intervals, their end points and integers c1, ..., cn from the standard input, 
computes the minimal size of a set Z of integers which has at least ci common elements with interval [ai, bi], for each i=1,2,...,n, 
writes the answer to the standard output. 

Input

The first line of the input contains an integer n (1 <= n <= 50000) -- the number of intervals. The following n lines describe the intervals. The (i+1)-th line of the input contains three integers ai, bi and ci separated by single spaces and such that 0 <= ai <= bi <= 50000 and 1 <= ci <= bi - ai+1.

Output

The output contains exactly one integer equal to the minimal size of set Z sharing at least ci elements with interval [ai, bi], for each i=1,2,...,n.

Sample Input

5
3 7 3
8 10 3
6 8 1
1 3 1
10 11 1

Sample Output

6

Source


差分约束系统的题。。。wa了很多次因为没注意清楚约束条件和隐藏条件

题目要求的是区间 [ai,bi]中至少有ci个数,一开始直接转化为 Sbi-Sai >= ci 个数,Sn代表前n个数中包含多少个,但其实Sbi-Sai包含的是(ai,bi],所以应该用区间Sbi-S(ai-1)。

但是ai有可能为0,所以统一都+1区间变为S(bi+1)-Sai>=ci

根据这个问题,加进去之间的点还必须满足一些隐藏条件: 

        1.对于a<=b, Sa <= Sb。

        2.同时一个区间[a,b]内最多也只能包含b-a+1个, 所以还有 Sb+1-Sa >= b-a+1 (这里区间是上面说的+1后)

        确定三个条件后,建立图论模型求最长路径 SaI+ci <= Sbi,从ai到bi连接一条权为ci的边


#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
using namespace std;


#define maxn 50005
#define inf 0x3f3f3f3f

struct edge
{
    edge(){}
    edge(int v_, int w_, int n) { v=v_; w=w_; next=n;}
    int v;
    int w;
    int next;
};

edge g[4*maxn];
int first[maxn], top;

void add(int u, int v, int w)
{
    g[top] = edge(v, w, first[u]);
    first[u] = top++;
}

int d[maxn];
int in[maxn];

void spfa(int s)  //因为图是连通的,所以可以用spfa
{
    memset(d, -inf, sizeof(d));
    memset(in, 0, sizeof(in));
    queue<int> que;
    que.push(s);
    d[s] = 0;

    while(!que.empty()){
        int u = que.front(); que.pop();
        in[u] = 0;

        for(int i = first[u]; i != -1; i = g[i].next){
            int v = g[i].v, w= g[i].w;
            if(d[u]+w > d[v]){      //求最长路径
                d[v] = d[u]+w;
                if(!in[v]){
                    in[v] = 1;
                    que.push(v);
                }
            }
        }
    }
}

int h[maxn]; //记录用到的点
int arr[maxn]; //用到的点从小到大存储

int main()
{
    int n;
    while(~scanf("%d", &n)){
        memset(h, 0, sizeof(h));
        memset(first, -1, sizeof(first));

        int s, e;
        int a, b, w;
        for(int i = 0; i < n; i++){
            scanf("%d%d%d", &a, &b, &w);
            add(a,b+1,w);
            h[a]=h[b+1]=1;
        }

        int cnt = 0;
        for(int i = 0; i < maxn; i++)
            if(h[i])
            arr[cnt++] = i;             //arr中存储点,从小到大


        for(int i = 1; i < cnt; i++){
            add(arr[i-1], arr[i], 0);       //相邻两个点满足Sa+0 <= Sb,从a到b一条边边权为0
            add(arr[i], arr[i-1], -(arr[i]-arr[i-1]));  //满足最多不超过b-a+1,  Sb+1-Sa<= b-a+1( Sb-(b-a+1)<=Sa)
         }                                              //从b到a连接边权-(b-a+1)
        

        spfa(arr[0]);
        printf("%d\n", d[arr[cnt-1]]);
    }
    return 0;
}


还有另外一种做法就是贪心+线段树,按每个区间的末端点从小到大排序。从第一个区间开始,每个区间检查有多少个数,小于c个,则从区间末端一直往前增加直到满足c个为止,这是O(n^2)。用线段树优化就可以达到O(nlogn),在进行区间更新时,优先选择先更新靠右的区间,同时返回增加了多少个数,然后再继续更新左边的区间,具体写在注释里了。

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>

using namespace std;

#define maxn 50005

int n;

struct node     //线段树节点
{
    node() {}
    node(int ll, int rr) { l = ll; r = rr;}
    int l, r;
    int sum;        //sum表示该节点区间上一共有多少个数了
    int inc;
};

node tr[4*maxn];

void build(int rt, int l, int r)
{
    tr[rt] = node(l, r);
    tr[rt].inc = tr[rt].sum = 0;

    if(l == r)
        return;

    int m = l+(r-l)/2;
    build(2*rt, l, m);
    build(2*rt+1, m+1, r);
}


int query(int rt, int ll, int rr)
{
    int l = tr[rt].l, r = tr[rt].r;
    int &sum = tr[rt].sum;
    int &inc = tr[rt].inc;
    int lc = 2*rt, rc = 2*rt+1;

    if(l == ll && r == rr)
        return sum;
    else{
        if(inc){
            tr[lc].inc = 1;
            tr[rc].inc = 1;
            tr[lc].sum = tr[lc].r-tr[lc].l+1;
            tr[rc].sum = tr[rc].r-tr[rc].l+1;
            inc = 0;
        }
    }

    int m = l+(r-l)/2;
    if(rr <= m)
        return query(lc, ll, rr);
    else if(ll > m)
        return query(rc, ll, rr);
    else
        return query(lc, ll, m)+query(rc, m+1, rr);
}



int seg_modify(int rt, int ll, int rr, int v)  //v表示需要增加的个数
{
    int l = tr[rt].l, r = tr[rt].r;
    int &sum = tr[rt].sum;
    int &inc = tr[rt].inc;
    int lc = 2*rt, rc = 2*rt+1;
    if(sum == r-l+1) return 0;

    int ret;

    if(l == ll && r == rr && sum+v>=r-l+1){   //如果需要刚好对应节点区间,且增加的个数使得该区间满了,则直接更新该节点整个区间
        ret = (r-l+1)-sum; //返回增加的个数
        sum = (r-l+1);
        inc = 1;
        return ret;
    }
    else{
        if(inc){
            tr[lc].inc = 1;
            tr[rc].inc = 1;
            tr[lc].sum = tr[lc].r-tr[lc].l+1;
            tr[rc].sum = tr[rc].r-tr[rc].l+1;
            inc = 0;
        }
    }


    int m = l+(r-l)/2;
    if(rr <= m)
        seg_modify(lc, ll, rr, v);
    else if(ll > m)
        seg_modify(rc, ll, rr, v);
    else{

        int left = v-seg_modify(rc, m+1, rr, v); //优先更新靠右边的区间,然后计算还要增加的个数
        if(left)
        seg_modify(lc, ll, m, left);
    }

    ret = tr[lc].sum+tr[rc].sum - tr[rt].sum;
    tr[rt].sum += ret;
    return ret;
}

struct range    //保存输入区间的节点
{
    int l, r;
    int c;
    bool operator <(const range& t) const
    {
        return r < t.r;
    }
};

range a[maxn];

int main()
{
    while(~scanf("%d", &n)){
        for(int i = 0; i < n; i++)
            scanf("%d%d%d", &a[i].l, &a[i].r, &a[i].c);
        sort(a, a+n);

        int ub = a[n-1].r;
        build(1, 0, ub);
        for(int i = 0; i < n; i++){
            int cnt = query(1, a[i].l, a[i].r);
            if(cnt < a[i].c)
                seg_modify(1, a[i].l, a[i].r, a[i].c-cnt);
        }

        printf("%d\n", query(1, 0, ub));
    }
    return 0;
}





【POJ 3169】差分约束 #include<cstdio> #include<iostream> #include<cstring> #include<algorithm> #include<cmath> #include<cctype> #include<queue> using namespace std; int n,ml,md; typedef pair<int,int> pii; #define mk(a,b) m 阅读详情

相关推荐

从时序迷宫到稳定通信:FSMC配置中的时间参数深度解析与实战避坑指南

本文深入解析STM32 FSMC配置中的时间参数,特别是AddressSetupTime和DataSetupTime的实战配置技巧。通过STM32F407连接SRAM的实际案例,提供从理论计算到CubeMX配置的全流程指南,帮助开发者避免常见时序陷阱,确保稳定通信。

nginx7reverse的博客 82

POJ 1201 Interval (查分约束系统)

题意翻译 区间取数 题目描述 有n个区间,在区间[ai,bi]中至少取任意互不相同的ci个整数。求在满足n个区间的情况下,至少要取多少个正整数。 输入输出格式 输入格式 多组数据。 第一行的一个整数T表示数据个数。对于每组数据,第一行包含一个整数nn(11<=nn<=5000050000)表示区间数。以下nn行描述区间。输入的第(i+1)行包含三个整数ai,bi...

abc0372的博客 185

SQL实现数据仓库ETL:分层设计、增量抽取与性能优化实践

在数据仓库建设过程中,ETL(抽取、转换、加载)是数据流转的核心环节。传统观点常将ETL与专业工具或大数据框架绑定,但在中小规模数据场景下,基于SQL的ETL方案凭借低门槛、高可维护性和直观的排错体验,成为高效且务实的选择。本文从ETL的基础概念出发,阐述数据仓库分层(ODS、DWD、DWS、ADS)中每层ETL的定位与职责,重点剖析增量抽取策略(时间戳、主键、日志)下的SQL实现方式,以及数据清洗、去重和格式化的常见写法。同时,结合真实项目经验,分享慢SQL优化技巧、任务调度依赖设计、幂等性保障和常见问题

weixin_33290540的博客 345

POJ1201 Intervals 差分约束

一、内容 You are given n closed, integer intervals [ai, bi] and n integers c1, ..., cn. Write a program that: reads the number of intervals, their end points and integers c1, ..., cn from the standard inp...

Tizzi的博客 1115

手把手教您 Claude 桌面端无需账号订阅,免费接入国产自定义大模型(Claude Desktop 绕过订阅限制,接入任意自定义 AI 模型)

无需官方账号,也能畅玩Claude桌面端!本文详解Claude Desktop如何跳过登入接入自定义大模型,轻松解锁Cowork、Code等强大功能🚀

XiaoqiangClub的博客 5411

C 语言多文件编程 : 大型程序的组织与管理

本文介绍了C语言多文件编程的核心概念与实践方法。主要内容包括:1. 多文件编程的必要性:解决单文件编程在大型项目中的维护和协作问题;2. 文件组织方式:头文件(.h)负责声明接口,源文件(.c)实现具体功能;3. 编译链接过程:分阶段编译和链接多个源文件;4. 头文件设计原则:包含接口声明、使用保护机制、保持自包含性;5. 模块化实践:通过示例展示学生信息管理系统的模块划分;6. 构建工具:介绍Makefile的编写和使用方法。文章还提供了创建静态库和动态库的指导,并强调了模块化设计、信息隐藏等软件工程原则

2503_91057718的博客 1947

poj 1201 Interval

题目链接:http://poj.org/problem?id=1201 题意:给你n个区间和每个区间至少要出多少个数,问你整个区间最少需要出多少个数 思路:设Si为小于i的整个区间需要出的个数,则有,S(b + 1) - S(a) &gt;= c,为了保证整张图是一个连通图,加上隐含的S(i + 1) - Si &gt;= 0,S(i + 1) - Si &lt;= 1. 于是一个查分约束系...

Kona的博客 359

39、高频 LLC 谐振转换控制系统动态优化算法分析与研究

本文针对高频下LLC谐振转换器动态性能差的问题,提出一种基于谐振电容器充放电估计动态切换时间的优化控制算法。通过改进状态轨迹控制方法,突破传统算法在谐振频率与开关频率相等条件下的限制,并结合新型采样策略有效抑制电压过冲。算法在MATLAB和SABER中完成仿真验证,并搭建基于STM32F407的原型系统进行测试,结果表明该方法显著缩短动态响应时间,提升系统稳定性。研究为高频、高功率密度开关电源的动态优化提供了可行解决方案。

linux6sysadmin的博客 111

POJ 1201 Intervals (差分约束+SPFA)

Intervals Time Limit: 2000MS   Memory Limit: 65536K Total Submissions: 18595   Accepted: 6976 Description You are given n closed, integer intervals [ai, bi] and n i...

weixin_33997389的博客 205

某手短视频用户主页视频列表爬虫实战:从原理到完整实现

随着短视频平台的迅猛发展,某手(为保护平台隐私,本文以“某手”代指实际目标)已经成为国内最大的短视频社交平台之一,拥有数亿日活用户。对于数据分析师、内容创作者和市场营销人员而言,获取某个用户主页的视频列表具有重要的研究价值——无论是分析头部创作者的内容策略,还是监测竞品的发布频率与互动数据,爬虫技术都成为不可或缺的工具。然而,在2024-2025年的技术环境下,某手已经构建了多层次的反爬机制:包括接口签名加密、请求参数动态混淆、设备指纹检测、IP行为分析以及Web端无限滚动加载的异步数据获取方式。

2201_76125261的博客 540

rk3588 适配以太网(百兆)

虽然 RK3588 的 GMAC 控制器原生支持千兆速率(10/100/1000 Mbps),但在某些工业控制、物联网网关或成本敏感型硬件设计中,开发者会选择将其配置为 百兆以太网(Fast Ethernet) 模式。

weixin_35723192的博客 218

POJ 1201 Intervals (差分约束系统, 贪心+线段树)

题目类型  Dijkstra算法的运用 题目意思 中文题目描述 解题方法 先枚举地位的范围(因为第1件物品必须在交易中出现所以范围区间的左端点就是 L1-m -> L1 右端点范围是 L1 -> L1+m) 确定范围后就是类似Dijkstra算法的贪心过程 d[i] 表示交易终点停在第 i 个物品时总共所需的花费 那么每次取最小的 d[i]

yunyouxi0's blog 1130

华为OD机试 - 物流仓储多维度成本利润综合查询系统 - 二维数组(Python/JS/C/C++ 新系统 100分)

本专栏收录于《华为OD机试真题(Python/JS/C/C++)》。刷的越多,抽中的概率越大,私信哪吒,备注华为OD,加入华为OD刷题交流群,每一题都有详细的答题思路、详细的代码注释、3个测试用例、为什么这道题采用XX算法、XX算法的适用场景,发现新题目,随时更新。某物流企业在全国多个仓库开展仓储业务,需要对不同仓库、不同时段的入库成本、出库收入和库存损耗进行综合统计分析,用于生成 日报、周报和月报。字段说明及取值范围如下:warehouses: int[] 扁平化数组 [w0d0in, w0d0out,

学Java,找哪吒 308

POJ1201-Intervals-线段树+贪心

原题链接 题意:给定一些区间,每个区间里必须取ci个数,这些数组成一个集合z,求z的最少的元素数 思路:由于如果两个区间如果有重复取的元素,那么这个元素一定是在左边的这个区间的最右边的那些元素。所以我们按照区间的右边界排序后,总是如果当前区间还需要取数,那么就从右往左取还没有被取的数即可。然后就可以用线段树来维护一段区间内已经被取走的数的总数。这样问题的复杂度就降到了O(NlogN)的程度了#i

HowieMen的博客 786

华为的C语言编程规范.pdf

华为技术有限公司内部技术规范。本规范制定了编写C语言程序的基本原则、规则和建议。从代码的清晰、简洁、可测试、安全、程序效率、可移植各个方面对C语言编程作出了具体指导。

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

POJ - 1201 Intervals 差分约束 || 贪心 + 线段树

传送门:POJ 1201 题意:给出n个三元组(ai, bi, ci),找出一组元素数目最少的整数集合,使得集合中包含在[ai, bi]之间的数不少于ci个。 思路:设d[i]表示[0..i]区间内选中了几个整数,则题给条件可以转化为d[bi] - d[ai - 1] >= ci,并且由于d[i]是一个前缀和函数,还满足 0   代码:#include #include #include #

WA是一笔财富 357

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

poj 1201 Intervals 线段树+贪心

http://poj.org/problem?id=1201题意:给定区间[l,r]和对应的数c,表示该区间内至少有c个点,现问为了使每个区间上均符合条件,整个数轴上至少要有多少个点。#include #include #include #include #include #include #include #include #include #include using namespace st

smilesundream的博客 631

WINCC7.3破解文件

WINCC7.3硬件够破解文件,有需要的下载!WINCC7.3硬件够破解文件,有需要的下载!

POJ - 1201 AcWing 362. Intervals(差分约束)(贪心+线段树)

题干: You are given n closed, integer intervals [ai, bi] and n integers c1, …, cn. Write a program that: reads the number of intervals, their end points and integers c1, …, cn from the standard input, c...

苍界的博客 268

poj-1201-Intervals(差分约束)

题目:1201-Intervals 思路:题目是意思是有n个区间[ai,bi],每个区间至少需要选ci个数.求出新的集合Z在满足所有约束条件下,至少包含多少个数。 用Si 表示1 - i 中被选出的数的个数. 不等式条件: 1、Si >= Si - 1 ,从1 到 i 中选的数必定不会比从1 到 i -1中选的数少。 2、Si - Si-1 <= 1 =>> Si-1 >= Si - 1, 相邻之间选的数的个数差不会超过1个数。 3、Sb - Sa-1 >= c =&g

qq_45880043的博客 1175

poj 百练 Intervals 区间覆盖

算法的思想:首先对于所有的节点根据起始坐标按照从小到大进行排序。定义两个变量from和to,分别记录前一个区间的起始坐标和停止坐标。然后看下一个节点:(from1,to1) case 1:if(from1>=to) then 合并 from不变;to修改为to和to1中的较大者。 case 2:if(from1 and update the from and to #include #

lightblueme的专栏 487

POJ Intervals (最小费用最大流)

题目: LINK 给定 N 个带权的开区间,第 i 个区间覆盖(ai, bi),权为 wi。现在要你挑出一些区间使得总权值最大,并且满足实轴上任意一个点被覆盖不超过 K 次。(1 首先要将每个区间的端点离散化,1..M,另加源 s=0,汇 t=M+1;对每个点 i (0 对每个区间(ai, bi)加边(ai’, bi’, 1, -wi),其中ai’, bi’分别表示 ai, bi

Napoleon 956

POJ 1201 Interval (Spfa 差分约束系统)

POJ 1201 ZOJ 1508 Interval 题目大意有一个序列,题目用n个整数组合[ai,bi,ci] [a_i,b_i,c_i]来描述它,[ai,bi,ci][a_i,b_i,c_i]表示在该序列中处于[ai,bi][a_i,b_i]这个区间的整数至少有cic_i个。如果存在这样的序列,请求出满足题目要求的最短的序列长度是多少。如果不存在则输出 -1。(0≤ai≤bi≤50000,1≤

AIDreamer 615

poj1201 - Intervals

想看更多的解题报告: http://blog.youkuaiyun.com/wangjian8006/article/details/7870410                                   转载请注明出处:http://blog.youkuaiyun.com/wangjian8006   题目大意:有n个区间,每个区间有3个值,ai,bi,ci代表,在区间[ai,bi]上至少要选择ci个

贰圣 3856

poj1201(贪心+树状数组)

网上的题解都用啥差分约束系统。。。太高端,不会玩,额。。这题把数据按b的大小进行从小到大排序。然后每次取最右边的数据,用树状数组维护,真的是很方便#include #include #include #include #define mem(a) memset(a,0,sizeof(a)) using namespace std; const int MAX=5*1e4+20; typedef

西天取经~ 706

POJ 1201 差分约束系统 / 贪心 + BIT + 并查集

题意 传送门 POJ 1201 Intervals 题解 差分约束系统 间区间和转化为前缀和之差。设 S[i]S[i]S[i] 为区间 [0,i][0,i][0,i] 内数字的个数,则区间约数转化为 S[bi]−S[ai−1]≥ciS[b_i]-S[a_i-1]\geq c_iS[bi​]−S[ai​−1]≥ci​,明显是一个差分约束系统的模型。不过,需要增加约数,以保证得到的解是有意义的。前缀和 SSS 单调不减,且长度为 111 的区间至多能选取 111 个数,即 S[k]−S[k−1]≥0,S[k]−

neweryyy的博客 202

POJ - 1201 Intervals(贪心+数据结构)

POJ - 1201 Intervals(贪心+数据结构) 考虑把所有线段按照右端点 bbb 从小到大排序,依次考虑每一条线段的要求: 如果已经满足要求则跳过 否则尽量选择靠后的数(因为之后的线段的右端点都在这条线段的右边,这样容错更高) 所以,我们可以建一个数组,f[i]f[i]f[i] 表示 iii 数字是否选择(填111或000),扫一遍[l,r][l,r][l,r] 区间求和,然后从后往前贪心放数即可。 对于每条线段需要 O(r−l+1)O(r−l+1)O(r−l+1)。所以最坏情况下 O(n

00后的博客 572

Intervals POJ - 1201 (区间约束 - 贪心!?)

这里只介绍一种不用线段树,不用什么SPFA的一种写法, 上面那 2 种写法已经有大佬详细介绍过:tp门 题意: n 个区间,每个区间 l --- r 要插 k 个眼,问最少插多少个眼 题解: 在一条线上某一个点有 2 种可能1.要么这里插一个眼                                                    2.要么这里是一个空位 这个眼尽量插后面一点,可...

qq_40644471的博客 327
上一篇: hdu 1394 逆序数
下一篇: poj 1275 差分约束
HuanTongH
博客等级 码龄12年 7粉丝 110原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值