Subsegments (线段树)

程序员Sasha需要在一个数组的每个固定长度的子段中找到恰好出现一次的最大元素。输入包含数组长度n和子段长度k,输出n-k+1行,每行对应一个子段中的唯一最大值。解题方法是采用双指针和线段树,线段树用于维护区间内出现一次的元素数量,并通过二分查找确定最大值。

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

 Subsegments

time limit per test

1 second

memory limit per test

256 megabytes

input

standard input

output

standard output

Programmer Sasha has recently begun to study data structures. His coach Stas told him to solve the problem of finding a minimum on the segment of the array in , which Sasha coped with. For Sasha not to think that he had learned all, Stas gave him a new task. For each segment of the fixed length Sasha must find the maximum element of those that occur on the given segment exactly once. Help Sasha solve this problem.

Input

The first line contains two positive integers n and k (1 ≤ n ≤ 105, 1 ≤ k ≤ n) — the number of array elements and the length of the segment.

Then follow n lines: the i-th one contains a single number ai ( - 109 ≤ ai ≤ 109).

Output

Print nk + 1 numbers, one per line: on the i-th line print of the maximum number of those numbers from the subarray ai ai + 1 … ai + k - 1that occur in this subarray exactly 1 time. If there are no such numbers in this subarray, print "Nothing".

Examples

input

Copy

5 3
1
2
2
3
3

output

Copy

1
3
2

input

Copy

6 4
3
3
3
4
4
2

output

Copy

4
Nothing
3

题目大意:一个序列,给出一个窗口大小为k,求每个窗口中只出现一次且最大的数是多少。

解题思路:双指针保证每次线段树中只有k个数被插入,然后线段树维护一下左右区间各有多少个只出现1次的数。

然后在线段树上二分,如果右区间有出现过一次的数就尽量走右区间,否则走左区间。

#include<bits/stdc++.h>
using namespace std;
#define inf 0x3f3f3f3f
#define pb(x) push_back(x)
 
const int N  = 1e5+5;
set<int>s;
map<int,int>mmp;
int a[N],b[N];
vector<int>v;
 
struct node
{
    int val,sz,kid;
}t[N*4];
 
void upd(int rt,int l,int r,int pos,int val)
{
    if(l==r)
    {
        t[rt].sz+=val;
        if(t[rt].sz==1)t[rt].kid=1;
        else t[rt].kid=0;
        return ;
    }
 
    int m=(l+r)>>1;
    if(pos<=m) upd(rt<<1,l,m,pos,val);
    else upd(rt<<1|1,m+1,r,pos,val);
    t[rt].kid=t[rt<<1].kid+t[rt<<1|1].kid;
    t[rt].val=t[rt<<1].val+t[rt<<1|1].val;
}
 
int ask(int rt,int l,int r)
{
    if(l==r)
    {
        return v[l-1];
    }
    int m=(l+r)>>1;
    if(t[rt<<1|1].kid!=0)
    {
        return ask(rt<<1|1,m+1,r);
    }
    else if(t[rt<<1].kid!=0)
    {
        return ask(rt<<1,l,m);
    }
    else return inf;
}
 
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1; i<=n; i++)
    {
        scanf("%d",a+i);
        v.pb(a[i]);
    }
    sort(v.begin(),v.end());
    v.erase(unique(v.begin(),v.end()),v.end());
    for(int i=1;i<=n;i++)
    {
        b[i]=lower_bound(v.begin(),v.end(),a[i])-v.begin()+1;
    }
    int l=1,r=0;
    while(r<n)
    {
        if(r-l+1<k)
        {
            r++;
            upd(1,1,n,b[r],1);
        }
        else
        {
            upd(1,1,n,b[l],-1);
            l++;
        }
        if(r-l+1==k)
        {
            int tmp=ask(1,1,n);
            if(tmp==inf)puts("Nothing");
            else printf("%d\n",tmp);
        }
    }
}

 

from pulp import * import pandas as pd # 模拟原材料数据(增加部分长材料,降低缺陷影响) data = { '原材料长度(米)': [5.5, 5.5, 6.2, 7, 7, 5.8, 6.5, 7.5, 6, 8.2, 6.8, 6.8, 5.6, 7.3, 6.1, 8, 5.9, 6.3, 7.8, 6.7, 5.4, 7.4, 6.9, 8.1, 7.6, 5.7, 6.4, 8.3, 6, 7.9, 5.5, 6.2, 7.1, 6.8, 5.8, 7.3, 6.9, 7.5, 5.6, 6.4, 6.6, 7, 8, 5.9, 7.7, 6.5, 7.2, 6.1, 5.4, 8.2, 6.7, 7.8, 5.5, 6.6, 7, 5.8, 8, 6.9, 7.2, 6.3, 8.1, 5.6, 7.4, 6.1, 6.8, 7.3, 5.7, 7, 6.5, 5.8, 8.2, 7.5, 6, 7.7, 6.6, 6.2, 7.3, 5.5, 7, 6.9, 8, 7.4, 6.3, 10, 10, 10], # 新增3根10m材料 '缺陷位置(米)': [1, 3, 2, 1.5, 4, 1.2, 2.3, 1, 2.8, 1.3, 2.1, 5, 1.1, 3.1, 1.7, 2.5, 3, 1.9, 1.2, 2.4, 0.8, 3, 2, 2.2, 1.6, 2.7, 1.8, 0.9, 1.1, 2.9, 1.3, 3.2, 2.3, 1.9, 2.5, 3, 2, 1.6, 1, 2.2, 2, 3.1, 1.5, 1.9, 2.6, 1.1, 2.7, 3, 1.5, 2, 2.9, 1.2, 2.1, 3.2, 1.7, 1, 2.3, 2.5, 3, 2.4, 1.9, 3.1, 2, 1.8, 2.1, 1.4, 2.6, 2.5, 3, 1.2, 2.7, 3, 1.1, 2.3, 2.1, 3.1, 1.5, 2.4, 1.8, 2.5, 2.6, 1.7, 3, 0, 0, 0], # 新增材料无缺陷 '缺陷长度(米)': [0.3, 0.2, 0.4, 0.2, 0.3, 0.5, 0.3, 0.6, 0.4, 0.5, 0.3, 0.2, 0.2, 0.4, 0.5, 0.3, 0.4, 0.3, 0.4, 0.3, 0.3, 0.2, 0.5, 0.4, 0.3, 0.4, 0.2, 0.3, 0.5, 0.2, 0.4, 0.3, 0.5, 0.2, 0.4, 0.3, 0.2, 0.4, 0.3, 0.5, 0.4, 0.3, 0.3, 0.2, 0.3, 0.5, 0.4, 0.3, 0.4, 0.2, 0.4, 0.3, 0.2, 0.4, 0.3, 0.3, 0.4, 0.5, 0.4, 0.3, 0.2, 0.4, 0.3, 0.5, 0.2, 0, 0, 0], # 新增材料无缺陷 '单价(元/根)': [17, 17.33, 20.59, 24.41, 24.05, 17.33, 22, 24.77, 19.83, 27.64, 23.32, 23.69, 17.66, 24.77, 19.83, 27.64, 18, 21.27, 26.57, 22.91, 16.68, 25.85, 22.91, 27.64, 26.2, 17.33, 22, 28.72, 18, 27.64, 16.68, 20.95, 23.69, 23.69, 17.66, 25.13, 24.05, 25.49, 17.33, 20.95, 22, 24.05, 28, 19.83, 25.85, 22.41, 24.41, 20.59, 17, 27.64, 22.91, 26.57, 16.36, 22, 24.05, 17.66, 28, 23.69, 24.41, 21.27, 27.27, 17, 25.49, 19.83, 23.69, 25.13, 17.33, 24.41, 22, 17.33, 28, 25.85, 19.41, 25.85, 22, 21.27, 25.13, 16.68, 23.32, 23.69, 27.27, 25.85, 20.59, 30, 30, 30] # 新增材料单价 } max_len = max(len(v) for v in data.values()) for k in data: data[k] += [None] * (max_len - len(data[k])) raw_materials = pd.DataFrame(data) # 生成可用子段(简化逻辑,允许无缺陷材料整根使用) def generate_subsegments(row): L = row['原材料长度(米)'] if pd.isna(L) or L <= 0: return [] s = row['缺陷位置(米)'] if not pd.isna(row['缺陷位置(米)']) else 0 d = row['缺陷长度(米)'] if not pd.isna(row['缺陷长度(米)']) else 0 if s == 0 and d == 0: # 无缺陷时整根可用 return [L] segments = [] if s > 0: segments.append((0, s)) if (s + d) < L: segments.append((s + d, L)) sub_lengths = [end - start for start, end in segments if (end - start) > 0.001] return sub_lengths raw_materials['subsegments'] = raw_materials.apply(generate_subsegments, axis=1) # 订单需求(降低部分数量,或增加长材料需求) orders = [ { 'lengths': [1.6, 2.2, 1.8, 2.4, 1.7, 2.3, 1.5, 2.0], 'quantities': [200, 200, 140, 140, 100, 100, 60, 60], # 降低需求数量 'per_set': {l: 1 for l in [1.6, 2.2, 1.8, 2.4, 1.7, 2.3, 1.5, 2.0]} } ] required_lengths = orders[0]['lengths'] required_quantities = {l: q for l, q in zip(orders[0]['lengths'], orders[0]['quantities'])} per_set = orders[0]['per_set'] # 创建优化问题(移除锯口损耗,先验证可行性) prob = LpProblem("Optimal_Cutting_Problem", LpMinimize) x = LpVariable.dicts('x', [(idx, j, l) for idx in raw_materials.index for j, sub_len in enumerate(raw_materials.loc[idx, 'subsegments']) for l in required_lengths if sub_len >= l], lowBound=0, cat='Integer') y = LpVariable.dicts('y', raw_materials.index, cat='Binary') # 目标函数 prob += lpSum([y[idx] * raw_materials.loc[idx, '单价(元/根)'] for idx in raw_materials.index]) # 约束1:满足订单需求 for l, q in required_quantities.items(): prob += lpSum([x[(idx, j, l)] for idx in raw_materials.index for j in range(len(raw_materials.loc[idx, 'subsegments'])) if (idx, j, l) in x]) >= q # 约束2:子段长度限制(暂时移除锯口损耗) for (idx, j, l) in x: sub_len = raw_materials.loc[idx, 'subsegments'][j] prob += l * x[(idx, j, l)] <= sub_len # 暂时不考虑锯口,验证可行性 # 约束3:材料使用与切割关联 for (idx, j, l) in x: prob += x[(idx, j, l)] <= y[idx] * (raw_materials.loc[idx, 'subsegments'][j] // l) # 求解问题 solver = PULP_CBC_CMD(msg=False) prob.solve(solver) # 解析结果 if prob.status == LpStatusOptimal: material_cuts = {} for idx in raw_materials.index: if y[idx].value() == 1: cuts = {} subsegments = raw_materials.loc[idx, 'subsegments'] for j in range(len(subsegments)): for l in required_lengths: if (idx, j, l) in x: count = x[(idx, j, l)].value() if count > 0: if l not in cuts: cuts[l] = 0 cuts[l] += count material_cuts[idx] = cuts total_pieces = {l: sum(cuts.get(l, 0) for cuts in material_cuts.values()) for l in required_lengths} total_sets = min(total_pieces[l] // per_set[l] for l in required_lengths) print("============= 切割结果 ==============") for idx, cuts in material_cuts.items(): print(f"材料 {idx} (长度: {raw_materials.loc[idx, '原材料长度(米)']}m):") for l, cnt in cuts.items(): print(f" - 切割 {cnt} 根 {l}m 部件") print() print("============= 总套数 ==============") print(f"可组成完整套数: {total_sets} 套") print(f"各部件总数量: {total_pieces}") else: print("未找到可行解,尝试调整原材料或订单需求") 修改代码,不可能没有最优解
最新发布
05-12
题目 基于附件中的缺陷数据和表3中的订单需求,建立数学模型,制定最优切割方案。 附件 |原材料长度(米)|缺陷位置(米)|缺陷长度(米)|单价(元/根)| | ---- | ---- | ---- | ---- | |5.5|1|0.3|17| |5.5|3|0.2|17.33| |6.2|2|0.4|20.59| |7|1.5|0.2|24.41| |7|4|0.3|24.05| |5.8|1.2|0.5|17.33| |6.5|2.3|0.3|22| |7.5|1|0.6|24.77| |6|2.8|0.4|19.83| |8.2|1.3|0.5|27.64| |6.8|2.1|0.3|23.32| |6.8|5|0.2|23.69| |5.6|1.1|0.2|17.66| |7.3|3.1|0.4|24.77| |6.1|1.7|0.5|19.83| |8|2.5|0.3|27.64| |5.9|3|0.4|18| |6.3|1.9|0.3|21.27| |7.8|1.2|0.4|26.57| |6.7|2.4|0.3|22.91| |5.4|0.8|0.3|16.68| |7.4|3|0.2|25.85| |6.9|2|0.5|22.91| |8.1|2.2|0.4|27.64| |7.6|1.6|0.3|26.2| |5.7|2.7|0.4|17.33| |6.4|1.8|0.2|22| |8.3|0.9|0.3|28.72| |6|1.1|0.5|18| |7.9|2.9|0.2|27.64| |5.5|1.3|0.4|16.68| |6.2|3.2|0.3|20.95| |7.1|2.3|0.5|23.69| |6.8|1.9|0.2|23.69| |5.8|2.5|0.4|17.66| |7.3|3|0.3|25.13| |6.9|2|0.2|24.05| |7.5|1.6|0.4|25.49| |5.6|1|0.3|17.33| |6.4|2.2|0.5|20.95| |6.6|2|0.4|22| |7|3.1|0.3|24.05| |8|1.5|0.2|28| |5.9|1.9|0.3|19.83| |7.7|2.6|0.5|25.85| |6.5|1.1|0.2|22.41| |7.2|2.7|0.4|24.41| |6.1|3|0.3|20.59| |5.4|1.5|0.2|17| |8.2|2|0.5|27.64| |6.7|2.9|0.3|22.91| |7.8|1.2|0.4|26.57| |5.5|2.1|0.5|16.36| |6.6|3.2|0.4|22| |7|1.7|0.3|24.05| |5.8|1|0.4|17.66| |8|2.3|0.2|28| |6.9|2.5|0.3|23.69| |7.2|3|0.4|24.41| |6.3|2.4|0.3|21.27| |8.1|1.9|0.5|27.27| |5.6|3.1|0.4|17| |7.4|2|0.3|25.49| |6.1|1.8|0.5|19.83| |6.8|2.1|0.2|23.69| |7.3|1.4|0.3|25.13| |5.7|2.6|0.4|17.33| |7|2.5|0.2|24.41| |6.5|3|0.3|22| |5.8|1.2|0.5|17.33| |8.2|2.7|0.4|28| |7.5|3|0.3|25.85| |6|1.1|0.3|19.41| |7.7|2.3|0.5|25.85| |6.6|2|0.4|22| |6.2|3.1|0.2|21.27| |7.3|1.5|0.3|25.13| |5.5|2.4|0.4|16.68| |7|1.8|0.5|23.32| |6.9|2.5|0.3|23.69| |8|2.6|0.4|27.27| |7.4|1.7|0.2|25.85| |6.3|3|0.5|20.59|表3:订单的具体切割需求 表格 订单号 订单需求对象 订单量(套) 宽度目标(米) 高度目标(米) 窗框单价(元/套) 1 学校教学楼 120 1.6 2.2 480 2 酒店客房 80 1.8 2.4 680 3 医院病房 60 1.7 2.3 550 4 政府办公楼 40 1.5 2.0 420 说明 (1)利用率 =(总用料量 - 切割后的总余料量)/总用料量,其中总用料量含锯口宽度。 (2)题中切割损失率及利用率的研究对象是总用料,而非单根原材料。
05-12
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值