寒假第一周解题报告

寒假第一周解题报告  刘金宗

一: 食物链

 

题目链接:https://vjudge.net/contest/146798#problem/D

题目大意:有一种食物链A吃B, B吃C, C吃A 。给n个动物, 但是不知道他们是哪个物种, 给出k句话,有两种陈述方式:第一种说法是"1 X Y",表示X和Y是同类。 第二种说法是"2 X Y",表示X吃Y。

 其中有一些是假话, 输出假话的个数。满足三个任意一个就表示是假话:

1) 当前的话与前面的某些真的话冲突,就是假话;

2) 当前的话中X或Y比N大,就是假话;

3) 当前的话表示X吃X,就是假话。

数据范围:1 <= N <= 50,000    0 <= K <= 100,000;

解题思路:这是一道并查集的问题, 可以把三个物种分成三个区间 [1 n], [1 + n, 2 n], [1 + 2n, 3n]这样考虑 如果x y 是同类, 那么 x 和 y就在一个集合内(他们的father是相同的) 如果x吃y 那么 x和 y + n 应该在一个集合内; 同理还有 x + n, y + n, x + 2n, y + 2n 一次类推。 所以每次只需要判断是否在一个集合内, 就可以知道是不是假话, 如果是真话, 则需要把他们再并到相应的集合中。

 

二:

Frequent values

题目链接:https://vjudge.net/contest/146798#problem/B

题目大意:多组数据, n 和 q  之后一行 给n 个数,  已经是从小到大排好的, 之后有q个询问,  每个询问两个数l, r;  问区间 l r  中出现次数最多的数出现了几次。

数据范围:1 ≤ n, q ≤ 100000   −100000 ≤ ai ≤ 100000

解题思路:这道题需要用到RMQ算法, 再稍微注意点细节。 首先是想到了用一个数组cont【i】表示到当前num[i]出现的最多次数, 之后再用rmq 。

这道题需要注意的是查找的时候, 当左边界正好是两个数的分界的时候,正常查找, 如果不是  那么就会出错, 所以要看左边界这个数有几个,  单独特判扫一下, 左边界移动之后的一个新的范围再查找, 但还需要特别注意, 如果左右边界值相同, 那么左边界移动可能会移动到右边界右边, 那么之后就会re, 所以这个时候直接用r – l + 1 就可以了 。

 

三:  I.O.U.

题目链接:https://vjudge.net/contest/146774#problem/G

题目大意: 给定n个人, 你知道他们之间的债务关系, 问最小的债务和为多少。

数据范围:1 ≤ n ≤ 100; 0 ≤ m ≤ 104

解题思路:这道题看了题解之后很简单, 几句代码就写完了。 思想是看成有一个超级大的银行, 也就是一个数组, 每个人借钱还是外借钱都通过这个银行, 最后要看的就是他们的和/2。 自己想了一下, 这个思路的确没错。 我之前想了建树。。。各种跑偏。

注意 最后求和要取abs

 

四:

Generating Sets

题目链接:https://vjudge.net/contest/146774#problem/E

题目大意:给定n个数的数列Y,每个数都不同,这是数列是由数列X生成的。X中每个数都不同,并且生成方法有三种

1、保持原来的

2、x替换成x*2

3、x替换成x*2+1

需要求使X中最大数尽量小的数列X。

数据范围:1 ≤ n ≤ 50 000  1 ≤ yi ≤ 109

解题思路:  没做这题之前还不会队列, 思路是找出最大值, 然后/2 看有没有相同的  有的话就继续除, 没有的话就把它放回去 但是没有一个好的办法每次都找出最大值, 如果在循环里用sort 的话复杂度就是O(n^2lgn)而n是5e4, 肯定会T, 于是就上网上搜了题解, 发现应该用队列这个东西,并且可以每次取出的都是最大值, 如果有一个数之后一直除到了0还是放不了  这个数就是最大值了, 其他的数在变小也没有意义了, 就可以直接break了。

 

队列用priority_queue<int> q; 

这样q.pop();得到的就是一个最大值;

这道题yi的数据范围是1 ≤ yi ≤ 109 ,     所以要用map来一个vis数组表示集合内是否出现了这个数。

 

 

posted @ 2017-01-14 20:50  ZZZZone  阅读(189)  评论(0编辑  收藏  举报