[2018.11.03 T1] 游戏攻略

暂无链接

游戏攻略

GISPZJZ 在玩一款火爆的游戏,游戏中有nnn个技能点,编号分别为1,2,…,n1,2,…,n1,2,,n。有些技能 点可以直接学习,还有一些技能点需要你已经学习某些技能点,才能够学习。一开始 GISPZJZ 没有学习任何技能点,现在 GISPZJZ 想知道,他最多能够学习技能池里的多少个技能。

输入:

第一行一个正整数nnn​。

接下来 nnn 行,第i+1i+1i+1 行先输入一个整数 sis_isi,接下来输入sis_isi 个正整数 as1,as2,…,asia_{s_1},a_{s_2},…,a_{s_i}as1,as2,,asi。 表示学习第 iii 个技能,需要先学习的技能点。si=0s_i=0si=0 表示学习iii 技能没有任何前置条件。

输出:

一行一个整数 ,表示 GISPZJZ 能学习的最大技能数。

样例输入:

4
0
1 1
2 1 4
2 1 3

样例输出:

2

样例说明:

GISPZJZ 可以按顺序学习技能 1,技能 2,然后无法获得其他的技能点。

数据范围:

对于 10%10\%10%的数据,1≤n≤10,1≤s1+s2+…+sn≤101≤n≤10,1≤s_1+s_2+…+s_n≤101n101s1+s2++sn10

对于 40%40\%40%的数据,1≤n≤500,1≤s1+s2+…+sn≤5001≤n≤500,1≤s_1+s_2+…+s_n≤5001n5001s1+s2++sn500

对于额外 10%10\%10%的数据,满足对任意 1≤i≤n,si≥11≤i≤n,s_i\ge 11insi1

对于额外 20%20\%20%的数据,满足对任意 1≤i≤n,si≤11≤i≤n,s_i≤11insi1

对于 100%100\%100%的数据,1≤n≤100000,1≤s1+s2+…+sn≤1000001≤n≤100000,1≤s_1+s_2+…+s_n≤1000001n1000001s1+s2++sn100000

题解

技能加点相当于一个图,每次将入度为000的点删去,更新其他点的入度,答案+1+1+1,类似于拓扑排序。

不知道为什么考场上脑子抽了写一个用优先队列的O(nlog⁡n)O(n\log n)O(nlogn)算法。。。

代码
#include<bits/stdc++.h>
using namespace std;
const int M=1e5+5;
struct sd{int id,du;};
bool operator<(sd a,sd b){return a.du>b.du;}
int ru[M],n,ans;
bool vis[M];
vector<int>mmp[M];
priority_queue<sd>dui;
void in()
{
	scanf("%d",&n);
	for(int i=1,j,a,b;i<=n;dui.push((sd){i,ru[i]}),++i)
	for(scanf("%d",&a),ru[i]=a,j=1;j<=a;++j)
	scanf("%d",&b),mmp[b].push_back(i);
}
void ac()
{
	for(sd f;!dui.empty();)
	{
		f=dui.top();dui.pop();
		if(vis[f.id])continue;
		if(f.du)break;
		vis[f.id]=1,++ans;
		for(int i=mmp[f.id].size()-1;i>=0;--i)
		dui.push((sd){mmp[f.id][i],--ru[mmp[f.id][i]]});
	}
	printf("%d",ans);
}
int main(){in(),ac();
<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
发出的红包

打赏作者

ShadyPi

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值