The Union of k-Segments CodeForces - 612D

本文介绍了一种算法,用于解决给定多个线段及一个整数k的情况下,找到包含所有满足条件(属于至少k个线段)的点的最小线段集合问题。文中提供了两种实现方法:差分数组法和线段树法,并附带详细的C++代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

You are given n segments on the coordinate axis Ox and the number k. The point is satisfied if it belongs to at least k segments. Find the smallest (by the number of segments) set of segments on the coordinate axis Ox which contains all satisfied points and no others.

Input

The first line contains two integers n and k (1 ≤ k ≤ n ≤ 106) — the number of segments and the value of k.

The next n lines contain two integers li, ri ( - 109 ≤ li ≤ ri ≤ 109) each — the endpoints of the i-th segment. The segments can degenerate and intersect each other. The segments are given in arbitrary order.

Output

First line contains integer m — the smallest number of segments.

Next m lines contain two integers aj, bj (aj ≤ bj) — the ends of j-th segment in the answer. The segments should be listed in the order from left to right.

Example

Input
3 2
0 5
-3 2
3 8
Output
2
0 2
3 5
Input
3 2
0 5
-3 3
3 8
Output
1
0 5

题解:
    该题需要离散化,因为按照题意,线段的端点和线都要记录,所以通过*2来离散化。
    两种方法:1.设一个数组,区间更新时,D[l]++;D[r+1]--;
         2.用线段树记录和更新访问次数


#include"stdio.h"
#include"cstdio."
#include"algorithm"
#include"string.h"
using namespace std;
const int max_n=1e6+1000; 
int A[max_n],B[max_n];
int C[max_n<<2],D[max_n<<2];
int sum[max_n<<2],time[max_n<<2];
int len;
void chang(int n)
{
    len=0;
    int i=0;
    D[++len]=C[++i];
    for(i=2;i<=n;i++)
    {
        if(C[i]-C[i-1]>1) D[++len]=C[i-1]+1;
        if(C[i]!=D[len]) D[++len]=C[i];
    }
}
int EF(int x)
{
    int l=1,r=len,mid;
    mid=(l+r)>>1;
    while(l<r)
    {
        if(D[mid]<x)
        l=mid+1;
        else if(D[mid]>x)
        r=mid-1;
        else return mid;
        mid=(l+r)>>1;
    }
    return mid;
}
int main()
{
    int n,k;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int i,j=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&A[i],&B[i]);
            A[i]*=2;
            B[i]*=2;
            C[++j]=A[i];
            C[++j]=B[i];
        }
        sort(C+1,C+1+j);
        chang(j);
        memset(sum,0,sizeof(sum));
        for(i=1;i<=n;i++)
        {
            int l=lower_bound(D+1,D+1+len,A[i])-D;//l=EF(A[i]);
            int r=lower_bound(D+1,D+1+len,B[i])-D;//r=EF(B[i]);
            sum[l]++;sum[r+1]--;
        }
        int ans=0;
        for(i=1;i<=len;i++)
        {
            ans+=sum[i];
            time[i]=ans;    
        } 
        int l=1,r=1,ret=0;
        int ll[max_n],rr[max_n];
        for(l=1;l<=len;l++)
        {
            r=l;
            if(time[l]>=k&&time[r]>=k)
            {
                while(time[l]>=k&&time[r]>=k&&r<=len-1)
                r++;
            }
            else
            continue;
            if(r>=len)
            {
                if(time[l]>=k&&time[r]>=k)
                {
                    ll[++ret]=D[l]/2;
                    rr[ret]=D[r]/2;
                    break;
                }
            }
            else
            {
                ll[++ret]=D[l]/2;
                rr[ret]=D[r-1]/2;
            }
            l=r;
        }
        printf("%d\n",ret);
        for(i=1;i<=ret;i++)
        printf("%d %d\n",ll[i],rr[i]);        
    }
}


线段树:

#include"stdio.h"
#include"string.h"
#include"algorithm"
#include"cstdio"
using namespace std;
const int max_n=1e6+10; 
int A[max_n<<1],B[max_n<<1];
int C[max_n<<2],D[max_n<<2];
int lazy[max_n*9],num[max_n*9];
int ll[max_n<<1],rr[max_n<<1];
int len,k;
void chang(int n)
{
    len=0;
    int i=0;
    D[++len]=C[++i];
    for(i=2;i<=n;i++)
    {
        if(C[i]-C[i-1]>1) D[++len]=C[i-1]+1;
        if(C[i]!=D[len]) D[++len]=C[i];
    }
}
int EF(int x)
{
    int l=1,r=len,mid;
    mid=(l+r)>>1;
    while(l<r)
    {
        if(D[mid]<x)
        l=mid+1;
        else if(D[mid]>x)
        r=mid-1;
        else return mid;
        mid=(l+r)>>1;
    }
    return mid;
}
void init(int l,int r,int rt)
{
    if(l==r)
    {
        num[rt]=0;
        return ;
    }
    int mid=(l+r)>>1;
    num[rt]=0;
    lazy[rt]=0;
    init(l,mid,rt<<1);
    init(mid+1,r,(rt<<1)|1);
}
void down(int rt)
{
    lazy[rt<<1]+=lazy[rt];
    lazy[(rt<<1)|1]+=lazy[rt];
    num[rt<<1]+=lazy[rt];
    num[(rt<<1)|1]+=lazy[rt];
    lazy[rt]=0;
}
void update(int L,int R,int val,int l,int r,int rt)
{
    if(l>=L&&r<=R)
    {
        lazy[rt]+=val;
        num[rt]+=val;
        return ;
    }
    if(lazy[rt])
    down(rt);
    int mid=(l+r)>>1;
    if(L<=mid)
    update(L,R,val,l,mid,rt<<1);
    if(R>mid)
    update(L,R,val,mid+1,r,(rt<<1)|1);
    num[rt]=min(num[rt<<1],num[(rt<<1)|1]);
}
int query(int L,int R,int l,int r,int rt)
{
    if(l>=L&&r<=R)
    {
        if(num[rt]>=k)
        return 1;
        else return 0;
    }
    if(lazy[rt])
    down(rt);
    int val=1;
    int mid=(l+r)>>1;
    if(L<=mid)
    val=min(val,query(L,R,l,mid,rt<<1));
    if(R>mid)
    val=min(val,query(L,R,mid+1,r,(rt<<1)|1));
    return val;
}
int main()
{
    int n;
    while(scanf("%d%d",&n,&k)!=EOF)
    {
        int i,j=0;
        for(i=1;i<=n;i++)
        {
            scanf("%d%d",&A[i],&B[i]);
            A[i]*=2;
            B[i]*=2;
            C[++j]=A[i];
            C[++j]=B[i];
        }
        sort(C+1,C+1+j);
        chang(j);
        init(1,len,1);
        for(i=1;i<=n;i++)
        {
            int l=EF(A[i]);
            int r=EF(B[i]);
            update(l,r,1,1,len,1);
        }
        for(i=1;i<=len;i++)
        query(i,i,1,len,1);
        int l=1,r=1,ret=0;
        for(l=1;l<=len;l++)
        {
            r=l;
            if(query(l,r,1,len,1))
            {
                while(query(l,r,1,len,1)&&r<=len-1)
                r++;
            }
            else
            continue;
            if(r==len)
            {
                if(query(l,r,1,len,1))
                {
                    ll[++ret]=D[l]/2;
                    rr[ret]=D[r]/2;
                    break;
                }
            }
            else
            {
                ll[++ret]=D[l]/2;
                rr[ret]=D[r-1]/2;
            }
            l=r;
        }
        printf("%d\n",ret);
        for(i=1;i<=ret;i++)
        printf("%d %d\n",ll[i],rr[i]);
    }
}


<think>嗯,用户询问的是IT领域的"usersegments"概念或工具。这似乎是个结合数据库和用户行为分析的术语,需要从多个引用中提取线索。引用[2]出现了"v$im_segments"这个Oracle数据库视图,里面的字段显示这是内存管理相关的技术。而引用[3]提到GLM-4模型能自动选择工具完成任务,这暗示用户分群可能用于个性化服务。看来需要分两层解释:首先是技术层面的数据库内存段管理(对应引用2),然后是应用层面的用户群体划分(引用3的逻辑延伸)。用户身份可能是DBA或产品经理,但提问比较模糊。考虑到站内引用里有具体数据库语法,技术解释应该更深入些。引用[1]和[4]暂时用不上,前者关于语义理解,后者是环境配置说明。准备用表格区分两种"user-segments"含义,DBA更关注字段说明,产品人员可能想要场景案例。需要强调视图名称是Oracle特有的,避免用户误以为是通用术语。</think> 在IT领域,“user-segments”通常涉及两种核心概念,具体含义需结合上下文区分: --- ### 一、**技术视角:数据库/存储中的内存段管理** 引用中提到的 `v$im_segments`(Oracle数据库视图)直接关联此场景: ```sql SQL> select segment_name,bytes,inmemory_size,INMEMORY_PRIORITY,INMEMORY_COMPRESSION from v$im_segments; -- 引用[2] ``` - **核心概念** `USER-SEGMENTS` 指数据库中被用户对象(如表、索引)占用的存储段,由Oracle自动管理,其物理存储在表空间中。 - **关键字段** | **字段名** | **作用** | |---|---| | `SEGMENT_NAME` | 对象名称(如表名) | | `BYTES` | 磁盘存储大小 | | `INMEMORY_SIZE` | 内存中压缩后的大小 | | `INMEMORY_PRIORITY` | 内存加载优先级 | - **典型场景** DBA通过监控这些段优化内存分配(如启用Oracle In-Memory特性加速查询)[^2]。 --- ### 二、**业务视角:用户群体细分(User Segmentation)** 引用[3]中GLM-4工具的意图理解能力支撑此场景: > “GLM-4 All Tools... 自主选择最合适的工具完成任务... 理解用户意图” [^3] - **定义**:根据用户行为(如点击流、购买记录)、属性(如地域、设备)划分目标群体。 - **技术实现**: - **数据层**:日志分析(Kafka + Flink) + 用户画像存储(HBase/ClickHouse) - **算法层**:聚类(K-means)、分类(RF/XGBoost) - **应用案例**: ```python # 简化的用户分群代码示例 from sklearn.cluster import KMeans user_features = load_user_data() # 加载用户特征矩阵 clusters = KMeans(n_clusters=5).fit_predict(user_features) # 划分5个用户群体 ``` --- ### 用户建议实践路径 | **角色** | **关注点** | **工具/方法** | |---|---|---| | 数据库管理员 | 监控内存段效率 | Oracle `V$IM_SEGMENTS`视图、AWR报告 | | 产品经理 | 精准用户运营 | Mixpanel/Google Analytics用户分群功能 | | 算法工程师 | 动态分群模型 | PySpark MLlib + 实时特征工程 | > 💡 **扩展思考**:结合引用[3]的意图识别能力,AI驱动型用户分群(如GLM-4)可实时生成动态分群策略,替代传统静态规则[^3]。 --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值