16.1113 模拟考试T1

本文介绍了一种算法,用于解决给定序列通过替换特定元素来最小化其代价的问题。该算法利用动态数组记录与每个数字相邻的所有数字,并选择修改后的数字为这些相邻数字的中位数以确保对答案贡献最小。
笔记
【问题描述】
给定一个长度为m的序列a,下标编号为1~m。序列的每个元素都是1~N的
整数。定义序列的代价为累加(1->m-1 abs(ai+1-ai))
你现在可以选择两个数x和y,并将序列?中所有的x改成y。x可以与y相等。
请求出序列最小可能的代价。
【输入格式】
输入第一行包含两个整数n和m。第二行包含n个空格分隔的整数,代表序
列a。
【输出格式】
输出一行,包含一个整数,代表序列最小的代价。
【样例输入 1】
4 6
1 2 3 4 3 2
【样例输出 1】
3
【样例输入 2】
10 5
9 4 3 8 8
【样例输出 1】
6
【样例解释】
样例 1 中,最优策略为将 4 改成 3。样例 2 中,最优策略为将 9 改成 4。
【数据规模和约定】
对于30%的数据,n,m<=100
对于60%的数据,n,m ≤ 2000。
对于100%的数据,1 ≤ n,m ≤ 100,000。

 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <ios>
 5 #include <vector>
 6 using namespace std;
 7 typedef long long ll;
 8 const int N = (int)1e5;
 9 int n, m, a[N+1];
10 vector<int> b[N+1];
11 int main(int argc, char *argv[]) {
12     freopen("note.in", "r", stdin);
13     freopen("note.out", "w", stdout);
14 
15     ios :: sync_with_stdio(false);
16     cin>>n>>m;
17     for (int i=1;i<=m;++i) cin>>a[i];
18     for (int i=1;i<=m;++i) {
19         if (i>1&&a[i-1]!=a[i]) b[a[i-1]].push_back(a[i]);
20         if (i<m&&a[i+1]!=a[i]) b[a[i+1]].push_back(a[i]);
21     }
22 
23     ll ans=0LL,sum=0LL;
24     for (int i=1;i<=n;++i){
25         if (!b[i].size()) continue;
26         sort(b[i].begin(),b[i].end());
27         int y=b[i][b[i].size()>>1];
28         ll before=0LL,after=0LL;
29         for (int j=0;j<b[i].size();++j) {
30             before+=abs(i-b[i][j]);
31             after+=abs(y-b[i][j]);
32         }
33         ans=max(ans,before-after),sum+=before;
34     }
35     cout<<sum/2-ans<<endl;
36     fclose(stdin);
37     fclose(stdout);
38     return 0;
39 }

 思路:动态数组记录下与每个数字相邻的所有数字,若是要修改这这个数字的话,肯定是从与它相邻的数字中间取中位数(先sort)这样对于答案的贡献肯定最小,before记录改之前的值,sum记录所有改之前的值,sum/2是因为相邻的两个数字肯定是互相相邻的,即每一个数字都被计算了两遍,ans记录对答案贡献较大的修改值,即遍历一遍检查修改1-N中的哪个数字,可以使答案更优,before-after为将i修改为

int y=b[i][b[i].size()>>1]前后差值,即修改i对答案的优化程度

 数据:见网盘我叫雷锋~  提取密码:gmcf

<think>嗯,用户希望优化这个SQL查询,表结构是conflict_info。首先,我需要看看原来的查询有什么问题。原SQL用了SELECT *,不过用户具体列出了所有字段,可能已经避免了不必要的字段,但还是要确认是否所有列都是必需的。比如,是否有字段在查询结果中并没有被使用到,可以去掉以减少数据传输和处理的开销。 接下来,索引方面。ORDER BY created_time DESC,如果没有索引的话,排序可能会很慢,尤其是在大表情况下。所以建议在created_time上创建降序索引,这样可以利用索引本身的有序性,避免全表扫描后的排序操作,提升查询速度。 然后,分页。用户可能没有分页,如果数据量很大,一次性返回所有结果会影响性能,增加网络传输时间。建议加上LIMIT和OFFSET,比如LIMIT 20 OFFSET 0,这样每次只取一部分数据,减少负载。 还要考虑查询是否频繁执行。如果是高频查询,可能需要更深入的优化,比如缓存策略或者调整索引。另外,检查表的数据量,如果conflict_info表非常大,可能还需要分区,比如按created_time做范围分区,这样查询时可以快速定位到相关分区,减少扫描的数据量。 字段列表方面,用户已经显式列出了所有字段,这样比SELECT *更好,因为表结构变化时不会影响到现有查询。不过还是要确认是否有冗余字段,比如某些字段是否可以从其他表关联得到,或者是否真的需要全部返回给前端。 执行计划分析也很重要,用EXPLAIN看看有没有全表扫描或者临时表的使用,根据执行计划调整索引。可能还需要复合索引,比如如果经常按照created_time和某个过滤条件查询,可以建联合索引。 另外,网络传输优化,如果字段很多,可以考虑压缩或者只查询必要字段,但用户已经列出了所有需要的字段,所以这点可能已经处理了。 总的来说,优化点主要是索引、分页、字段精简和分区。需要逐步实施这些优化步骤,并测试性能提升效果。</think>根据SQL优化原则,针对这个查询可以从以下几个方面进行优化(分步骤说明): 一、索引优化 1. 创建排序索引 当前查询使用`ORDER BY created_time DESC`,建议为`created_time`字段添加索引: ```sql CREATE INDEX idx_created_time_desc ON conflict_info(created_time DESC); ``` 数学依据:当排序字段有索引时,时间复杂度可从$O(n \log n)$降为$O(\log n)$ 二、查询优化 1. 分页处理(重要) 添加`LIMIT`分页限制,避免全表扫描: ```sql LIMIT 20 OFFSET 0 ``` 2. 字段精简(可选) 检查是否所有字段都需要返回,例如`register_file`等大字段会影响网络传输效率 三、表结构优化建议 1. 分区表(适用于海量数据) 如果数据量超过千万级,建议按时间分区: ```sql CREATE TABLE conflict_info PARTITION BY RANGE (created_time); ``` 四、完整优化后的SQL ```sql SELECT t1.id, t1.version, t1.creator, t1.created_time, t1.updator, t1.updated_time, t1.data_status, t1.group_id, t1.group_no, t1.dept_id, t1.tenant_id, t1.conflict_code, t1.conflict_status, t1.visit_reason, t1.visit_num, t1.visit_person, t1.reception_user_id, t1.reception_time, t1.service_type, t1.conflict_source, t1.conflict_type, t1.conflict_place, t1.conflict_place_detail, t1.accept_result, t1.accept_satisfied, t1.process_id, t1.conflict_flag, t1.report_account_id, t1.dispute_code, t1.put_off_time, t1.event_person_liable, t1.is_top, t1.emergency_degree, t1.acceptance_deadline FROM conflict_info t1 ORDER BY t1.created_time DESC LIMIT 20 OFFSET 0; ``` 五、性能验证建议 1. 执行计划分析 ```sql EXPLAIN ANALYZE [上述优化后的SQL] ``` 2. 索引效率验证公式: 查询响应时间应满足$T_{new} \leq \frac{T_{old}}{5}$(理想情况下) 优化要点总结: 1. 通过索引将排序时间复杂度从$O(n \log n)$降为$O(\log n)$ 2. 分页限制减少数据传输量 3. 分区表设计提升海量数据查询效率 4. 显式字段列表避免`SELECT *`的性能隐患 建议在优化后监控查询执行时间,如果仍存在性能瓶颈,可考虑添加覆盖索引或进行冷热数据分离。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

七情六欲·

学生党不容易~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值