2019牛客暑期多校训练营(第二场)

本文总结了多项ACM竞赛题目解法,包括随机游走概率计算、BM算法解决线性递推问题、利用priority_queue求解最小团问题、动态规划解决路径计数问题等。并分享了解题技巧及注意事项。

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

RankSolvedABCDEFGHIJ
9/4375/10ØO.OØOØOØO

O: 当场通过

Ø: 赛后通过

.: 尚未通过

A Eddy Walker

upsolved by viscaria

viscaria’s solution

考虑从点m出来,首先我们一定会先到m+1,m-1,然后就变化成一个随机游走,两个吸收壁的问题。以0与n为吸收壁,点i被n吸收的概率为 i / n i/n i/n(记住记住记住!!!!!)


B Eddy Walker 2

solved by chelly


chelly’s solution

BM算法解决线性递推,时间复杂度是 O ( k 2 log ⁡ n ) O(k^2 \log n) O(k2logn)的。
鸣谢dls的模板。

C Go on Strike!

unsolved


D Kth Minimum Clique

solved by chelly&viscaria


chelly’s solution

我们考虑将所有合法团丢进一个priority_queue里,然后不断弹出最小的,第 K K K个弹出的就是第 K K K小的。
具体来说,对于priority_queue中每个元素,都需要维护一个bitset表示外面的哪些点可以加入这个团。每次扩展的时候枚举bitset里的点扩展即可。但这样最坏情况是 O ( n 64 n k log ⁡ ( n k ) ) O(\frac{n}{64}nk \log (nk)) O(64nnklog(nk))的。但比赛时候放过了……
事实上,我们的扩展只需要两个策略:将目前下标最大的点换成下标更大的点;新加入一个下标更大的点。这样就是 O ( n 64 k log ⁡ k ) O(\frac{n}{64}k \log k) O(64nklogk)

E MAZE

upsolved by chelly


chelly’s solution

考虑dp,设 d p ( i , j ) dp(i,j) dp(i,j)表示走到 ( i , j ) (i,j) (i,j)的方案数。
d p ( i , j ) = ∑ k = l r d p ( i − 1 , k ) dp(i,j)=\sum_{k=l}^r dp(i-1,k) dp(i,j)=k=lrdp(i1,k),其中 g ( i , l ) = g ( i , l + 1 ) = . . . = g ( i , r ) = 0 g(i,l)=g(i,l+1)= ...=g(i,r)=0 g(i,l)=g(i,l+1)=...=g(i,r)=0
于是转移的dp可以表示成两行之间的矩阵乘法,对于修改我们就线段树维护矩阵乘法即可。

F Partition problem

solved by chelly&viscaria


chelly’s solution

一共有 ( 28 14 ) \binom{28}{14} (1428)种合法状态,对于每种合法状态想办法快速统计其价值即可。可以将 2 N 2N 2N分为左半边和右半边,维护一些东西,使得统计价值的过程更加快速即可。

G Polygons

upsolved by viscaria


viscaria’s solution

这道题是平面直线图的裸题,直接套模板就行了,主要值得注意的是建图,把点信息始终存在vector里,使排序的时候不会丢失每个点的定位,可以省去查找点的一个过程。

    for(int i=0;i<n;i++){
        for(int j=i+1;j<n;j++){
            if(dcmp(Cross(p[i][1]-p[i][0],p[j][1]-p[j][0]))==0)continue;
            pp[cnt2++]=GetlineIntersection(p[i][0],p[i][1]-p[i][0],p[j][0],p[j][1]-p[j][0]);
            h[i].push_back(seg(Dot(p[i][1]-p[i][0],pp[cnt2-1]-p[i][0]),cnt2-1));
            h[j].push_back(seg(Dot(p[j][1]-p[j][0],pp[cnt2-1]-p[j][0]),cnt2-1));
        }
        sort(h[i].begin(),h[i].end());
    }
    t.init(cnt2);
    for(int i=0;i<cnt2;i++){
        t.x[i]=pp[i].x;
        t.y[i]=pp[i].y;
    }
    for(int i=0;i<n;i++){
        int num=h[i].size(),u,v;
        for(int j=1;j<num;j++){
            u=h[i][j-1].p;
            v=h[i][j].p;
            t.AddEdge(u,v);
        }
    }

H Second Large Rectangle

solved by chelly&viscaria


chelly’s solution

首先求出一个最大的全1矩阵,然后把其四角分别扣成0,分别再做一次最大全1矩阵,四个数值中的最大值就是次大矩阵。


upsolved by chelly

chelly’s solution

求最大全1矩形还有个不需要用单调栈的做法。可以从上往下依次枚举每行,对于每列维护 l [ j ] , r [ j ] , h [ j ] l[j],r[j],h[j] l[j],r[j],h[j] h [ j ] h[j] h[j]表示第j列向上能到的高度, l [ j ] l[j] l[j] r [ j ] r[j] r[j]表示从第 j j j列,以 h [ j ] h[j] h[j]的高度,向左向右能扩展到哪里。比较好写。

I Inside A Rectangle

upsolved by chelly


chelly’s solution

J Subarray

solved by chelly


chelly’s solution

首先考虑如果是1e7个1或者-1,如何在O(n)时间内解决。可以参考一下dreamoon的这个代码。简单来说从左往右扫描,不断维护一个权值数组pre[x],表示目前前面的所有位置中<=x的有多少个。

然后考虑如何处理1e9的情况,在这种情况里,有很多段连续的-1因为个数太多,不会对其前面和后面造成影响,所以可以先维护出可能作为答案的区间。具体来说dp求出每个全1区间右端点向左能得到的最大和,左端点向右能得到的最大和。对于区间[l[i],r[i]]和[l[i+1],r[i+1]],如果从r[i]向左的最大和+从l[i+1]向右的最大和>=中间-1的个数,那么就合并这两个区间。最后会得到一些可能区间,对每一个区间实行上面提到的O(n)算法即可。容易发现可能成为答案端点的位置不超过3e7,所以时间复杂度是3e7的。

Dirty Replay

  • D题WA了一发,初始化的时候忘记把小于一个点编号的其它点删去了。
  • F题WA了一发,一开始以计数的错误思路去做的,也没有测试太多样例直接浪交了。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值