一篇来自ACM入门者的补题记录

最近有点懒,想着还有最后一篇博客没完成,是我最大的补题动力。

不过终于在camp过去三个月的时候完成了所有的补题博客,有点欣慰,下一个目标应该是补一补一年前暑期训练的题目…

文章目录

  • A.Aqours
  • C.御坂妹妹
  • C.吉良吉影的奇妙计划
  • E.Souls-like Game
  • G.穗乃果的考试

A.Aqours

题意:根结点为1 的有根树,对于每一个叶子结点uuu,问离其最近的编号&lt;u&lt;u<u的叶子结点到它的距离是多少。若不存在则输出−1-1−1。

思路:思维题。

我们假设 d[x]d[x]d[x] 为点x与离其最近的叶子结点的距离,初始时每个d[x]d[x]d[x]都处于未被更新的状态。对于每个叶子节点,向上搜索父节点,记搜索过程走的距离为sumsumsum,搜索期间不断更新d[x]d[x]d[x],直到遇上一个被更新过的 xxx 结点,搜索结果为ans=sum+d[x]ans = sum+d[x]ans=sum+d[x]。

因为 d[x]d[x]d[x] 可能是来自于自己的子结点,也可能是来自于父结点,单纯的向上更新是不够的,我们需要一个回溯操作将父结点的 d[x]d[x]d[x] 一并考虑进行更新。我们按编号从前往后搜索,自然保证了编号&lt;u&lt;u<u,而编号最小的那个叶子结点,会搜索到未被更新过的结点,查询结果为−1-1−1。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 3e6+1;
int fa[maxn],flag[maxn],d[maxn];
int ans;
int DFS(int x,int sum){if(d[x] != 0){ans = sum+d[x];d[x] = min(sum,d[x]);return d[x]+1;}int temp = 0x3f3f3f3f;if(x != 1)temp = DFS(fa[x],sum+1);d[x] = min(sum,temp);return d[x]+1;
}
int main()
{int n;scanf("%d",&n);fa[1] = 1;memset(flag,0,(n+1)*sizeof(int));memset(d,0,(n+1)*sizeof(int));for(int i = 1;i<n;i++){int a;scanf("%d",&a);fa[i+1] = a;flag[a] = 1;}for(int i = 1;i<=n;i++){if(!flag[i]){ans = -1;DFS(i,0);printf("%d %d\n",i,ans);}}return 0;
}

B.玖凛两开花
是一道匹配问题。
暂未解决。

C.御坂妹妹

题意:这题题意比较绕,简单来说就是有若干条直线:f(x)=kix+bif(x) = k_ix+b_if(x)=ki​x+bi​,找一条垂直于 xxx 的线段,使其与所有直线都有交点。问最短的线段长度。

思路:题解是求半平面交或是求上下凸包的解法,但我几何实在太差,好在这题也有用三分搜索过的解法。我们很容易想象到,当xxx趋向于正无穷或负无穷时,目标线段长度都是趋于无穷大的,而xxx趋于中间某个值时,目标线段长度最短。虽然没有严格的证明,但目标线段长度关于 xxx 的函数应该是满足凹函数性质的,满足三分搜索的条件。

关于三分搜索,我觉得也有两种写法。一种是比较常见的以精度作为搜索结束的条件,但这题要求的精度好像比较高,需要用longdoublelongdoublelongdouble型才能解决,还有一种就是用doubledoubledouble型,只设定搜索次数作为结束条件,而不考虑精度,我补题时采用的就是后一种写法。至于搜索次数和初始搜索区间,就真的凭感觉吧…

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e6+50;
double k[maxn],b[maxn];
int n;
double f(double x){double Max = -1e18,Min = 1e18;for(int i=1;i<=n;i++){Max =max(k[i]*x+b[i],Max);Min =min(k[i]*x+b[i],Min);}return Max-Min;
}
int main()
{scanf("%d",&n);for(int i=1;i<=n;i++)scanf("%lf%lf",&k[i],&b[i]);double l=-5e5,r=5e5;int t=120;double ans=1e18;while(t--){double len = (r-l)/3.0;double f1=f(l+len),f2=f(r-len);if(f1>=f2)l=l+len;elser=r-len;ans=min(ans,f1);ans=min(ans,f2);}printf("%.9f\n",ans);return 0;
}

C.吉良吉影的奇妙计划

题意:在纸上写下2n2n2n个字,n个’左’,n个’右’,当左右两个字写在一起时会变为两个’空’,不允许出现四个连续的’空’,问合法的计划有多少种。

思路:难得一道现场过的题目,Div2中的n <= 20,DFS模拟过程直接打表,Div1则需要考虑dp的做法。

#include<bits/stdc++.h>
using namespace std;
int n,n1,n2;
const int mod = 998244353;
long long ans;
long long kk[3];
void dfs(int tot,int k){if(tot > n)return;if(tot == n){ans++;return;}for(int i = 0;i<3;i++){if(k == 1 && i == 2 || i == 1 && k == 2)continue;if(k == 0 && i == 0)continue;if(i == 0 && kk[1] > 0 && kk[2] > 0){kk[1] -=1;kk[2] -= 1;dfs(tot+2,i);kk[1]+=1;kk[2]+=1;}else if(i != 0 && kk[i] > 0){kk[i] -= 1;dfs(tot+1,i);kk[i] += 1;}}
}
int main()
{int n;scanf("%d",&n);long long ans[22] = {0,1,2,6,14,38,100,268,726,1974,5404,14852,40972,113388,314632,875112,2439014,6810102,19045612,53341428,149589348};cout<<ans[n]<<endl;return 0;
}

E.Souls-like Game

题意:这场比赛过题较少的原因应该就是这题hh…这题的题意很难,翻译过来就是:n个3*3的矩阵,有两种操作:第一种是询问区间内矩阵相乘后的结果矩阵的元素之和,第二种是把区间内的矩阵统一修改为某一种矩阵。

思路:读懂了题意,模拟过程即可,唯一难点在于矩阵乘积是O(n3) 的,直接这样求会超时,但题目求的是元素之和,不是结果矩阵,所以在多个矩阵相乘时,可以预处理出上一个矩阵的列之和,然后只要拿下一个矩阵对应的元素去乘相应的列,再加起来存为下一次相乘时的列之和,这样复杂度就是O(n2),就可以过了。

c#include <bits/stdc++.h>
using namespace std;
const int maxn = 1e4+2;
const int mod = 998244353;
int p[maxn][3][3];
int main() {int n,m,op,l,r;scanf("%d%d",&n,&m);for(int i = 1;i<=n-1;i++)for(int j = 0;j<3;j++)for(int k = 0;k<3;k++)scanf("%d",&p[i][j][k]);while(m--){scanf("%d%d%d",&op,&l,&r);if(op==1){for(int i = 0;i<3;i++){for(int j = 0;j<3;j++){int a;scanf("%d",&a);for(int k = l;k<=r;k++)p[k][i][j] = a;}}}else{long long sum[2][3];for(int i = 0;i<3;i++)sum[l&1][i]=1;for(int k = l;k<r;k++){int f=k&1,g=!f;for(int i = 0;i<3;i++)sum[g][i]=0;for(int i = 0;i<3;i++)for(int j = 0;j<3;j++)sum[g][i]=(sum[g][i]+sum[f][j]*p[k][j][i])%mod;}printf("%lld\n",(sum[r&1][0]+sum[r&1][1]+sum[r&1][2])%mod);}}return 0;
}

G.穗乃果的考试

题意:给定一个 n×m 的 01 矩阵,记fif_ifi​​为恰有 i 个 1 的子矩阵的个数。
求:∑i=0nmi⋅fi\sum_{i=0}^{nm}i \cdot f_i∑i=0nm​i⋅fi​,​输出答案对 998244353 取模的结果。

思路:我们知道答案就是所有子矩阵中1的个数,预处理出 sum[i][j]sum[i][j]sum[i][j]为从以p11p_{11}p11​为左上角,以pijp_{ij}pij​为右下角的子矩阵中包含1的个数,那么很容易知道对于任意一个子矩阵(以pabp_{ab}pab​为左上角,以pcdp_{cd}pcd​为右下角)而言,这个子矩阵的贡献就是sum[c][d]+sum[a−1][b−1]−sum[c][b−1]−sum[a−1][d]sum[c][d]+sum[a-1][b-1]-sum[c][b-1]-sum[a-1][d]sum[c][d]+sum[a−1][b−1]−sum[c][b−1]−sum[a−1][d],我们很容易想到一个O(n4)O(n^4)O(n4)的朴素做法,这显然是不够的。考虑一个sum[i][j]sum[i][j]sum[i][j]被加的次数就是它作为左上角和右下角的次数,被减的次数就是它作为左下角和右上角的次数,这是由i,ji,ji,j决定的,只需要一个二重循环就能解决。

#include<bits/stdc++.h>
using namespace std;
const int maxn = 2e3+5;
const int mod = 998244353;
string S[maxn];
long long sum[maxn][maxn] = {0};
int main()
{int n,m;ios::sync_with_stdio(false);cin>>n>>m;for(int i = 1;i<=n;i++)cin>>S[i];long long ans = 0;for(int i = 1;i<=n;i++)for(int j = 1;j<=m;j++){sum[i][j] = sum[i-1][j]+sum[i][j-1]-sum[i-1][j-1]+S[i][j-1]-'0';ans = (ans+sum[i][j]*(i*j+(n-i)*(m-j)))%mod;ans = (ans-sum[i][j]*(i*(m-j)+j*(n-i))+mod)%mod;}cout<<ans<<'\n';return 0;
}

J.去音乐会
数论题目,与扩展欧几里得解不定方程有关。数论实在有点糟糕…
暂未解决。

2019 CCPC-Wannafly Winter Camp Day8 (Div2, onsite) 补题记录相关推荐

  1. 2019 CCPC-Wannafly Winter Camp Day1 (Div2, onsite)(补题记录)

    一篇来自ACM入门者的补题记录 文章目录 A.机器人 B.吃豆豆 C.拆拆拆数 E.流流流动 F.爬爬爬山 I.起起落落 J.夺宝奇兵 A.机器人 题意:有两条平行线段A,B,长度从1~n,机器人一开 ...

  2. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) 补题

    A Aqours 题解: https://www.cnblogs.com/qieqiemin/p/11251645.html D:吉良吉影的奇妙计划 (暴力打表) 题目描述 吉良吉影是一个平凡的上班族 ...

  3. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) A 题 Aqours (精巧的树形DP)

    题目链接: https://www.cometoj.com/contest/29/problem/A?problem_id=414 Aqours 题目描述 Aqours 正在 LoveLive! 决赛 ...

  4. CCPC-Wannafly Winter Camp Day8 (Div2, onsite)

    Replay Dup4: 厕所是个换换脑子的好地方? 要读题啊,不要别人不做,自己就跟着不做啊 X: 读题很重要啊!什么时候才能读对题 不演队友啊 D题看错题, 直到最后一小时才看懂 很多时候要看榜单 ...

  5. CCPC-Wannafly Winter Camp Day8 (Div2, onsite) 去音乐会

    题目链接 题目描述 在冬马曜子工作室的安排下,和纱会在维也纳休养a天,然后去日本开b-a天音乐会,并以b天为一周期不断循环.而根据Knight Records的工作安排,雪菜会去外地出差c天,然后休息 ...

  6. 阔力梯的树(2020 CCPC Wannafly Winter Camp Day2 Div.12 )dsu on tree

    题解: dsu on tree dsu on tree的基本步骤就不说了 看到这题询问结点的子树问题,而且询问时离线的,首先想到的dsu on tree的这个trick. 本题的难题就是如何维护结点所 ...

  7. 2019 CCPC wannfly winter camp Day 5

    C - Division 思路:我们考虑到一点,从大往小取得顺序是不会有问题的,所以可以直接主席树,但是开不下空间,我们可以log分段求. #include<bits/stdc++.h> ...

  8. CCPC-Wannafly Winter Camp Day3 (Div2, onsite) I 石头剪刀布(按秩合并并查集)

    题解:每次有两个事件: y y去挑战xx,如果赢了可以坐在x x的位置,打平或者输了就要被淘汰. 询问在进行所有一类事件后,有多少种情况可以让x x现在还没有被淘汰. 对于第二类事件,我们假设x x挑 ...

  9. 2019 CCPC wannfly winter camp Day 8

    E - Souls-like Game 直接线段树合并矩阵会被卡T掉,因为修改的复杂度比询问的复杂度多一个log,所以我们考虑优化修改. 修改的瓶颈在于打lazy的时候, 所以我们预处理出每个修改矩阵 ...

最新文章

  1. 极速发展的饿了么订单系统架构演进
  2. 使用LINUX SENDMAIL发送邮件
  3. 深入理解指针以及二级指针(指针的指针)
  4. MySQL数据库查询中的特殊命令
  5. 【Unity笔记】使用协程(Coroutine)异步加载场景
  6. 在Linux 6上使用UDEV解决RAC ASM存储设备名问题
  7. 【system generator】基于system generator的整数除法器设计
  8. VS2015编译Poco+openssl,使用Poco发送HTTPS请求
  9. Java二十三种设计模式 之代理(proxy)
  10. Python可以这样学(第二季:tkinter案例精选)-董付国-专题视频课程
  11. 话说这发表日志跟聊天似的简单很啊。
  12. oracle知识小结二
  13. redis数据类型之Hash
  14. 深入测试CCD坏点和噪点
  15. 需求分析报告或需求调研报告和需求规格说明书有什么区别?
  16. UE4蓝图基础04-变量和数组
  17. 百位LOL英雄联盟角色合集
  18. 红米1A显示器于笔记本win10环境下,如何设置颜色范围使得显示器亮度恢复成250nit
  19. ros_多消息同步回调(Synchronizer)
  20. 八大排序算法--堆排序

热门文章

  1. 外部波澜起伏,内心平静如常
  2. OpenCV之阈值化操作总结
  3. 主机连接wifi时,虚拟机VMware如何连接网络
  4. 谷歌验证码recaptcha接入
  5. 2022年版中国制冷设备市场深度分析与投资调研评估报告报告
  6. 请编写一个函数,接收两颗星星赤经和赤纬的角度作为参数,计算并返回这两颗星星所对弧的角度。
  7. Java之ByteBuffer详解
  8. 关于Direct3D11中字体的思考
  9. Python数据分析第三期--简述Pandas
  10. AIX7.1 安装配置 EMC Symmetrix 存储驱动软件