2021“MINIEYE杯”中国大学生算法设计超级联赛 第三场 赛后总结

1001.Bookshop

题意
  给定一棵树,树上的点有点权\(a_{i}\),每次给出一个询问\(x,y,w\),表示对于一条从\(x\)到\(y\)的路径上的每个点做一次判定,若该点\(a_{i}\geq w\),则使\(w=w-a_{i}\),否则不做操作,最后查询走完路径后\(w\)的权值。
关键trick
  (markdown还不太会,摆烂)这题我们第一眼就觉得需要树链剖分,然后我们考虑区间上如何处理询问。我们发现这种判定+修改的操作没法做到合并操作,所以必然只能一次判定/修改一个点,所以我们考虑能不能把询问离线,而对于每个点考虑每个经过这个点的询问的状态,并一起判定+修改。所以我们通过树链剖分将修改分为dfs序单调递减和dfs序单调递增的两种链,那么我们每次的操作相当于在一个数据结构里找到当前权值>=w的询问,并将其权值-w。考虑使用splay。这里的trick是将权值在[w,2w]内的询问暴力提取并暴力重新插入,[2w,+inf]内的询问打标记处理。即可通过此题。

1002.Destinations

题意
给定一棵树,有m个条件需要满足,每个条件给出s,t1,t2,t3,c1,c2,c3表示s->t1需要c1代价,s->t2需要c2代价,s->t3需要c3代价,需要为每个条件选择一条路径,并且要保证每个点最多被一个路径经过一次,在此基础上最小化代价和,无解输出-1。
关键trick
先考虑普通版本的3m条链最小化代价和(最大化收益和),这个题可以通过树形DP解决,f[i]表示i为根的子树的答案,sum[i]表示i的所有儿子的最大化收益和的和,f[i]=max(sum[i],sum[j]-f[j])(j,i∈路径k),可以通过树链剖分+线段树解决。然后关键在于怎么样满足m个条件均被满足。我们发现每个条件最多选一条路径,所以我们需要修改代价,让多选择一条路径的收益尽量大,观察到ci<=1e6,我们修改权值ci->1e6(m+1)-ci,则无论如何1e6m进制下的高位权值不可能被更改,至此转化完成,答案大于1e6*m^2有解。

1003.Forgiving Matching

题意
给定字符串S,T,长度n,m,存在通配符,对于i=0~m,计算S的每个起始位置的长度为m的子串与T匹配失配位置个数<=i的方案数。
关键trick
FFT匹配,翻转T,先匹配完美匹配的位置,再处理si!=''&&tj!=''&&si!=tj的位置个数,总个数减一下就获得了通配符匹配的个数。

1004.Game on Plane

题意
有n条直线,对于每个i,A选i条直线,B画一条直线,A要使交点个数尽量多,B要使交点个数尽量少,求交点个数
关键trick
无,纯贪心,sb题(赛中看到清华WA了一发于是没有先写,实际上就是很sb,只能说需要相信自己.jpg)

1005.Kart Race

暂无,缺

1006.New Equipments II

听说了补图的dinic,但是不太会,缺,希望自己能学会.jpg(感觉挺厉害的trick)

1007.Photoshop Layers

题意
未知,队友开的
关键trick
无,签到

1008.Restore Atlantis II

不会,没开,赛后看了觉得毒题

1009.Rise in Price

题意
n*n的网格图,每个点有ai,bi(随机生成),从(1,1)出发,每次只能走到(x+1,y)或者(x,y+1),并将走过的位置的ai,bi加起来,最后要\(sum\lbrace a_{i} \rbrace*sum\lbrace b_{i} \rbrace\)最大。\(n\leq100\)
关键trick

这题是一道非常具有思考意义的题,我们先考虑几个关键性质。
1、数值随机,意味着\(sum\lbrace a_{i} \rbrace\)与\(sum\lbrace b_{i} \rbrace\)的差值不会特别大。
2、结果要最大化\(sum\lbrace a_{i} \rbrace*sum\lbrace b_{i} \rbrace\),又有条件1,则\(sum\lbrace a_{i} \rbrace+sum\lbrace b_{i} \rbrace\)会相对较大
3、若考虑使用DP,对于在(i,j)位置的某两个方案i1:(x1,y1),i2:(x2,y2)。若(x1>x2,y1>y2)则i1一定比i2优,故保留的方案若按ai升序排序,bi必定是降序排序。
4、结合1,3,利用二维平面可知,一个位置的方案数不会特别大。
结合性质1、3、4我们可以得到算法1:暴力转移f[i][j],将所有合法方案直接暴力转移,可以测得一个点方案数不超过1000,可以通过此题。
结合性质1、2我们可以得到算法2:对于f[i][j]的方案,我们只保留\(sum\lbrace a_{i} \rbrace+sum\lbrace b_{i} \rbrace\)较大的1000(可以更小)个方案,每次转移归并合并即可。
两种算法均可通过此题。而我们队在赛中写的暴力枚举前17步,之后贪心取(当两种方案的\(sum\lbrace a_{i} \rbrace+sum\lbrace b_{i} \rbrace\)差值不大时两种方法都爆搜)的思想其实就是算法2的前身,只不过过于暴力,而算法2相当于在相同时间内将很多容错操作放在一起转移,大大加速了贪心算法。

1010.Road Discount

题意
n个点,m条边,每条边都有两种价格\(c_{i},d_{i},d_{i}\leq c_{i}\),\(d_{i}\)为一条边的折扣价格,问最多选择k条折扣边的最小生成树的权值(k∈(0,n)),保证n,ci<=1000。
关键trick

这题也是一道非常有思考意义的题。
算法1:这种题有一个典trick,我们发现若将折扣前的边设为白边,折扣后的边设为黑边,并将所有黑边的权值+w,则随着w的变化,选择黑边的数量会单调递增。考虑kruskal的过程就会发现,黑边的插入顺序是不变的,所以我们只需要找到刚好使用k条黑边的权值c。但是一次kruskal的复杂度是O(nm),不能接受。
我们思考如何优化边数,发现如果使用折扣边跑一次最小生成树,则最小生成树外的折扣边不会被使用(考虑krsukal的过程),则边数被降到了O(n^2),可以通过此题。
算法2:我们考虑一个简单的贪心,用非折扣边跑一遍最小生成树,然后再用算法1的trick将折扣边边数优化至O(n),考虑每次按照权值从小到大的顺序暴力插入一条折扣边,找到这条链上权值最大的边断开,将边的权值差丢进vector里。最后对vector sort一下,从大到小加即可处理询问。这个算法的关键在于,选择边的集合不变的情况下,插入的顺序不会改变节省的总代价(具体可以画图证明,这里不再赘述)

1011.Segment Tree with Pruning

题意
长度为n的区间的线段树的节点个数(给定一个k,当区间长度<=k时直接创建叶子节点并返回),n<=1e18
关键trick
记忆化搜索即可
我们考虑将n表示为二进制,如1001000011110
当n的最后一位为0时,左右区间长度一致,只有一个转移状态。而当最后一位为1时,会出现两个状态,一个是直接将n的最后一位抹去,一个是将n的最后一位进一后右移,相当于将二进制内一段连续的1变为1个1,则记忆化搜索中最多会出现不超过lognloglogn个状态。

1012.Tree Planting

毒题,不会

赛后总结:没有认真总结性质,只能说自己菜.jpg

上一篇:数据特征工程的一些trick(风控逾期预测为案例)


下一篇:开源控件ViewPagerIndicator的使用