Codeforecs 69E. Subsegments STL/线段树

本文介绍了一种利用滑动窗口解决寻找固定长度子数组中唯一出现一次的最大元素的问题,通过使用集合和映射数据结构实现高效查找。

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

E. Subsegments
time limit per test
2 seconds
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".

Sample test(s)
input
5 3
1
2
2
3
3
output
1
3
2
input
6 4
3
3
3
4
4
2
output
4
Nothing
3

----------------------------

To solve this problem you have to do a "move" subsegment and know :

 1. The set B of numbers, meeting once, with the function of extracting the maximum for O (logN)

2.The set of numbers appearing on this subsegments with keeping the number of times,that this number is found on this subsegments, with function of verifying how many times the number in this subsegments for O (logN).

 

While moving a segment from (a[i] .. a[i + k - 1]) for 1 item left (a[I + 1] .. a[I + k]) you have to:

1) Check whether a[i] with a[I + k]. If yes, then there is no need to modify the set, otherwise proceed to item 2 and 3.

2) Check how many times we have a[i] in the set A: if 2, then add a[i] to B, if 1, then remove it from  A and B. Do not forget to reduce the corresponding number of occurrences of a[i] in the current segment 1.

3) Check, how many times we have a[I + k] in the set A: if 0, then add a[i] in the B and A, if 1, then remove it from B. Do not forget to increase the corresponding number of occurrences of a[i] the current interval to 1.

 

After that, if the set is not empty, we should take peak from it.

 

So the asymptotics of this process will be O(NlogN).

 

As such data structures  set / map(for those who use C + +) and the Cartesian tree are suitable.

----------------------------------------

写的有点挫。。。

#include <iostream>
#include <map>

using namespace std;

map<int,int>mp;
map<int,int>::iterator it;
map<int,int>co;
int n,k;
int a[111111];

int main()
{
    cin>>n>>k;
    for (int i=1; i<=n; i++) cin>>a[i];
    for (int i=1; i<=k; i++)
    {
        mp[a[i]]++;
        if (mp[a[i]]==1)
        {
            co.insert(pair<int,int>(a[i],1));
        }
        else
        {
            if (co.find(a[i])!=co.end()) co.erase(a[i]);
        }
    }
    it=co.end();
    if (it!=co.begin()) it--;
    if (co.empty()) cout<<"Nothing"<<endl;
    else cout<<it->first<<endl;
    for (int i=k+1; i<=n; i++)
    {
        mp[a[i]]++;
        mp[a[i-k]]--;
        if (mp[a[i]]==1)
        {
            co.insert(pair<int,int>(a[i],1));
        }
        else
        {
            if (co.find(a[i])!=co.end()) co.erase(a[i]);
        }
        if (mp[a[i-k]]==1)
        {
            co.insert(pair<int,int>(a[i-k],1));
        }
        else
        {
            if (co.find(a[i-k])!=co.end()) co.erase(a[i-k]);
        }
        it=co.end();
        if (it!=co.begin()) it--;
        if (co.empty()) cout<<"Nothing"<<endl;
        else cout<<it->first<<endl;
    }
    return 0;
}








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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值