考试报告 模拟24

T1

改题时遇到的问题:

1.搜索时只有树才可以dfs(int x,int f)

2.注意开long long!!!!

题解:

思路不难想(可我考场上还是没想出来),问最小距离的最大值,显然是个二分答案,考虑check(两点之间的距离),上边界和下边界分别抽象成一个点,能不能到,就是看路径上有没有完全阻断的路,那么就可以将每个点按照ans/2的半径作圆,如果有交集就将其连边,那么就从上边界开始dfs,若能找到下边界说明不行,剪枝:先将k个点按照横坐标升序排列,建边的时候如果距离>ans就不用建边了

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<cstdlib>
 6 #include<algorithm>
 7 #define R register
 8 using namespace std;
 9 inline int read()
10 {
11     int x=0;char ch=getchar();
12     while(ch>‘9‘||ch<‘0‘)ch=getchar();
13     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
14     return x;
15 }
16 const int maxn=6005;
17 const double eps=1e-8;
18 int n,m,k;
19 struct node{
20     int v,nxt;
21 }e[maxn*maxn];int h[maxn],nu;
22 void add(int x,int y)
23 {
24     e[++nu].v=y;
25     e[nu].nxt=h[x];
26     h[x]=nu;
27 }
28 struct poin{
29     long long x,y;
30 }p[maxn];
31 bool cmp(poin a,poin b){return (a.x==b.x)?a.y<b.y:a.x<b.x;}
32 inline double cal(int i,int j){return (p[i].x-p[j].x)*(p[i].x-p[j].x)+(p[i].y-p[j].y)*(p[i].y-p[j].y);}
33 int v[maxn];
34 int dfs(int x)
35 {
36     if(x==k+1)return 0;
37     v[x]=1;
38     for(int i=h[x];i;i=e[i].nxt)
39     {
40         int y=e[i].v;
41         if(v[y])continue;
42         if(!dfs(y))return 0;
43     }
44     return 1;
45 }
46 inline int valid(double nw)
47 {
48     memset(v,0,sizeof v);
49     memset(h,0,sizeof h);
50     nu=0;
51     for(int i=1;i<=k;++i)
52     {
53         if(1.0*p[i].y>1.0*m-nw)add(0,i),add(i,0);
54         if(1.0*p[i].y<nw)add(k+1,i),add(i,k+1);
55         for(int j=i+1;j<=k;++j)
56         {
57             if(1.0*(p[j].x-p[i].x)>nw)break;
58             if(cal(i,j)<nw*nw)
59                 add(i,j),add(j,i);
60         }
61     }
62     return dfs(0);
63 }
64 int main()
65 {
66 //freopen("starway9.in","r",stdin);
67     n=read(),m=read(),k=read();
68     for(R int i=1;i<=k;++i)
69         p[i].x=read(),p[i].y=read();
70     sort(p+1,p+k+1,cmp);
71     double l=0.0,r=1.0*m;
72     while(r-l>1e-8)
73     {
74         R double mid=(l+r)/2.0;
75         if(valid(mid))    l=mid;
76         else r=mid-eps;
77     }
78     printf("%.9lf\n",l/2.0);
79 }
80 /*
81 g++ 1.cpp  -o 1
82 ./1
83 10 5 2
84 1 1
85 2 3
86
87 */

正解:最小生成树,将k个点和上下边界都互相连边,从边界开始跑prim, 由于不断加入的是这个点到已经生成的树上权值最小的边,所以这些边不断地取max,找到另一边界后就可以break了,此时已将在原图上建出一条连接两边界的链了,并且都是最小值,那这其中的max就是答案

T3

原式可以看作是斜率的式子,提个负号,那么就是这个点到其祖先中斜率最大的那个,维护一个凸包(就是后面的斜率都比上一个大),这样在处理一个节点时,比较这个节点和栈顶元素,如果不满足大于即不能是凸包,就不断pop,直到并用其更新ans值,注意回溯时要重新放回去,这能拿80,

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 using namespace std;
 6 #define int long long
 7 inline int read()
 8 {
 9     int x=0;char ch=getchar();
10     while(ch>‘9‘||ch<‘0‘)ch=getchar();
11     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
12     return x;
13 }
14 inline double min(double x,double y){return x<y?x:y;}
15 const int maxn=500005;
16 int n,c[maxn],fa[maxn],dep[maxn];
17 int sta[maxn],top=0;
18 double ans[maxn];
19 struct node{
20     int v,nxt;
21 }e[maxn];int h[maxn],nu;
22 void add(int x,int y)
23 {
24     e[++nu].v=y;
25     e[nu].nxt=h[x];
26     h[x]=nu;
27 }
28 inline double cal(int i,int j)
29 {
30     return 1.0*(double)(c[i]-c[j])/(double)(dep[i]-dep[j]);
31 }
32 int num=0;
33 int sta2[maxn],top2;
34 void dfs(int x)
35 {
36     int down=top2;
37     while(x!=1&&top>=2&&(cal(x,sta[top])<cal(sta[top],sta[top-1])))
38         sta2[++top2]=sta[top--];
39     ans[x]=-1.0*cal(x,sta[top]);
40     sta[++top]=x;
41     for(int i=h[x];i;i=e[i].nxt)
42     {
43         int y=e[i].v;
44         dep[y]=dep[x]+1;
45         dfs(y);
46     }
47     --top;
48     while(top2>down)
49         sta[++top]=sta2[top2--];
50     return;
51 }
52 signed main()
53 {
54     //freopen("data","r",stdin);
55     n=read();
56     for(int i=1;i<=n;++i)c[i]=read();
57     for(int i=2;i<=n;++i)fa[i]=read(),add(fa[i],i);
58     dep[1]=1;
59     dfs(1);
60     for(int i=2;i<=n;++i)
61         printf("%.10lf\n",ans[i]);
62 }
63 /*
64 g++ 1.cpp -o 1
65 ./1
66
67 8
68 31516 11930 18726 12481 79550 63015 64275 7608
69 1 1 2 4 2 4 5
70 */

再用上链表实现的倍增思路

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstdlib>
 4 #include<cstring>
 5 using namespace std;
 6 #define int long long
 7 inline int read()
 8 {
 9     int x=0;char ch=getchar();
10     while(ch>‘9‘||ch<‘0‘)ch=getchar();
11     while(ch<=‘9‘&&ch>=‘0‘){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
12     return x;
13 }
14 inline double min(double x,double y){return x<y?x:y;}
15 const int maxn=500005;
16 int n,c[maxn],dep[maxn],pre[maxn][25],fa[maxn];
17 double ans[maxn];
18 struct node{
19     int v,nxt;
20 }e[maxn];int h[maxn],nu;
21 void add(int x,int y)
22 {
23     e[++nu].v=y;
24     e[nu].nxt=h[x];
25     h[x]=nu;
26 }
27 inline double cal(int i,int j){return 1.0*(double)(c[i]-c[j])/(double)(dep[i]-dep[j]);}
28 int que[maxn],fro=1,bac=0;
29 void bfs()
30 {
31     que[++bac]=1;
32     while(fro<=bac)
33     {
34         int x=que[fro++];
35         dep[x]=dep[fa[x]]+1;
36         int y=fa[x];
37         for(int j=20;j>=0;--j)
38             if(pre[pre[y][j]][0]&&cal(pre[y][j],pre[pre[y][j]][0])>cal(x,pre[y][j]))y=pre[y][j];
39         if(pre[y][0]&&cal(y,pre[y][0])>cal(x,y))y=pre[y][0];
40         pre[x][0]=y;
41         ans[x]=-1.0*cal(x,y);
42         for(int j=1;j<=20;++j)
43             pre[x][j]=pre[pre[x][j-1]][j-1];
44         for(int i=h[x];i;i=e[i].nxt)
45             que[++bac]=e[i].v;
46     }
47 }
48 signed main()
49 {
50     //freopen("data","r",stdin);
51     n=read();
52     for(int i=1;i<=n;++i)c[i]=read();
53     for(int i=2;i<=n;++i)fa[i]=read(),add(fa[i],i);
54     bfs();
55     for(int i=2;i<=n;++i)
56         printf("%.10lf\n",ans[i]);
57 }
58 /*
59 g++ 1.cpp -o 1
60 ./1
61
62 8
63 31516 11930 18726 12481 79550 63015 64275 7608
64 1 1 2 4 2 4 5
65 */

原文地址:https://www.cnblogs.com/casun547/p/11369452.html

时间: 2024-10-12 06:50:22

考试报告 模拟24的相关文章

[考试反思]0214省选模拟24:揣测

还行吧.至少不算炸.虽说这个分的确也不怎么样. 考试的时候觉得$T2$是个计数,部分分好像还挺多,应该可想. 然后在$T2$上刚了仨小时,因为做的题不够会的知识点也不够所以只有签到分. $T1$的话贪心暴力随便写就是了用不到一个小时. 然而其实$T1$是最可想的一个...应该吧... 这种难度的题以目前水平想出一道可能就要几个小时,所以一场考试基本只能压一道题. $T2$早就有了$36$分的思路,然而最关键的一步居然是个其他题的结论,听说过但没记住,于是就没了. 得亏$T3$是个恶心的原题,然而

2019/8/27 校内模拟赛 考试报告

A.挑战(challenge.cpp) 首先令\(x_i=max(a_i-k,0)\),即破坏第\(i\)个防御区域的代价. 设\(dp_i\)表示从\(1...i\)需要的最小代价,有状态转移方程:\(dp_i=min(dp_j)+x_i\),其中\(i-L\le j\le i-1\). 初始化边界\(dp_0=0,dp_{1...n+1}=inf\).动态规划求出\(dp_{n+1}\)即可. 时间复杂度\(O(n^2)\),可以用ST表/线段树优化到\(O(nlogn)\). B.乌龟(t

2019.10.08考试报告

T1 用一个堆维护最小的是谁,每次加入一个值x时查询堆顶是否小于x,有则买top卖x,之后分为是不是反悔操作判断要不要把pop. 然而好像其他人都push两个来进行反悔操作. 1 #include<iostream> 2 #include<cstdio> 3 #include<cmath> 4 #include<cstring> 5 #include<queue> 6 #define int long long 7 using namespace

考试总结 模拟99

考试过程 最后一场两位数的考试,死的很惨 开题后T1看了一眼,第一眼觉得是最长上升子序列,线性dp的那种 然后就去刚O(n)的算法,不久就听到大多数人敲键盘的声音,比较着急, 尤其是旁边人自信满满的动作....然后就通过写暴力稳定心态.写完之后没试样例就继续想 思考效率指数级降低...想要对旁边人予以“反击”,可还是没有思路 1h多后有看题发现样例过不了,虽然之前先看了一眼样例但是并不能把握每一个细节 又读了半天题最终在打算弃掉T1前读懂了... 浪费了1h30min??顿时一股来自西西伯利亚的

2019.07.12考试报告

这次被山大附中的大佬暴踩了. 0-1.5h 考试期间心态依旧很好,T1打了一个暴力,期望得分60分,T2打了dfs拿35分左右,T3直接输出样例,期望得分0分 1.5~2h 突然发现T1好像能O(q*n*log2(n))搞出来(类似退化版山海经),打了出来过了样例,还是不放心便对拍了一下,但是数据真的好难造啊T_T. 2~3.5h 有点不在状态,有可能是利哥中午的鼾声太魔性了,想了想T2的dp,成功把T2搞到了10分(hx输出样例15分) 考试结束 最终得分50+10+0=60分,拿了rank7

考试心得 模拟5

(本次考后总结 专门为 可能到来的某”特殊“访客 公开,其他的总结若有需要请与本人联系) 再次崩掉 0+30+5=35(排名33) 几乎每次都在30的边缘徘徊 先说过程: 考前:吃完饭后心态挺好,没有过度焦虑 坐下来,跟旁边人扯了一会loj的某运势,我————大凶,诸事不宜,但我不信邪,恩,心态完好 老师误把网断了,我以为用不着了就把浏览器关了,但当我再想打开的时候, 完了....凉了.... 被迫重启.... 关键是FTP被关了,,,编译的外部工具没了.......   *** 幸亏我会一点终

2019.08.01考试报告

-3h:有点紧张,前两次考试爆炸,这次很关键(无论是对于信心还是对于分机房) -1h:好好地休息了一个中午,没浪- +1h:快速打完T1的暴力40分+线段树的正解,一边对拍一边开始打T2 +1.5h:woc这T2样例是假的吧?!打了两种dfs发现输出是一样的都是20,便不管它了 +2h:码完T3的暴力,码的过程中有点紧张,因为双线卡题而且T2暴力样例过不了. +2.5h:疯狂检查T2是不是读错题了,发现并没有,感觉要完戏了... +3h:卡了卡常,发现了T3的对手操作其实就是逻辑左移,但是没想出

考试心得 模拟12

先干的T2  1个小时,啥都没打出来, 想到了线段树,分块,莫队,都能骗到不少分,但我都没想到怎么实现 其中有20分钟浪费在了没打完的线段树上,想好了再打,别浪费时间 T1 自己努力够到的天花板,只是别人的起跑线 找了10分钟规律,找到了父节点与儿子节点的关系,然后用手去打表,想要卡常,但你能不能先想到严密的思路再去用手码 又浪费了10分钟去摸索打表,然后发现没用,心思在打表卡常上卡了好久, 发现只能暴力建树,还有一个半小时结束考试,开始打,坑坑迟迟,lca板子不熟练,没信心 比往常数组多开成2

2019.08.05考试报告

用了几个月的Linux竟然对拍是错的: 原来./后面要直接加东西,我以前考试的对拍都是假的(怪不得造出的数据在运行对拍程序时不会变)... 话说,我竟然活到了现在? -1h:和skyh日常互相毒奶(我又成功了(大雾)) 0h:考试开始,心里面确实放空了,不去想自己的命运,自己的归属,专心干T1. 1h:T1顺利码出80分并用假对拍拍对了,同时开始打T3,好像是个奇袭? 1.5h:还是选择了直接去写暴力,因为这题的暴力分有50分,很肥很肥... 2h:有了T1的80分再去写T2就比较轻松了,发现是