GALAXY OJ NOIP2019联合测试1-总结
概要
本次比赛考的不是很好,400分的题只拿了180分。。。(失误失误)
题目
T1:数你太美(预期100 实际60)
题目大意:
在两个序列中找两个最小的数进行组合,使这个最小整数最小。
解析:
只要根据题目模拟就可以了。。。。。。。
(玄学60分!!!)
code :
60分代码
1 #include<iostream> 2 using namespace std; 3 4 int n,m; 5 int a[100000]; 6 int b[100000]; 7 int main() 8 { 9 cin>>n>>m; 10 int minn=2e9,minm=2e9; 11 for(int i=1;i<=n;i++) 12 { 13 cin>>a[i]; 14 if(minn>a[i]) 15 { 16 minn=a[i]; 17 } 18 } 19 for(int j=1;j<=m;j++) 20 { 21 cin>>b[j]; 22 if(minm>b[j]) 23 { 24 minm=b[j]; 25 } 26 } 27 if(minn==minm) 28 { 29 cout<<minn; 30 return 0; 31 } 32 else 33 { 34 cout<<min(minn*10+minm,minm*10+minn); 35 } 36 return 0; 37 }
AC代码
1 #include<cstdio> 2 #include<algorithm> 3 using namespace std; 4 int n,m; 5 int a[10],b[10]; 6 int at[10],bt[10],ct[10]; 7 int t1,t2; 8 void cmp(int x,int y) 9 { 10 if(x<y) 11 { 12 printf("%d",x); 13 } 14 else 15 { 16 printf("%d",y); 17 } 18 } 19 int main() 20 { 21 scanf("%d%d",&n,&m); 22 for(int i=1;i<=n;i++) 23 { 24 scanf("%d",&a[i]); 25 at[a[i]]=1; 26 } 27 for(int i=1;i<=m;i++) 28 { 29 scanf("%d",&b[i]); 30 bt[b[i]]=1; 31 } 32 for(int i=0;i<10;i++) 33 { 34 ct[i]=at[i]+bt[i]; 35 } 36 sort(a+1,a+n+1); 37 sort(b+1,b+m+1); 38 for(int i=0;i<10;i++) 39 { 40 if(ct[i]==2) 41 { 42 printf("%d",i); 43 return 0; 44 } 45 } 46 t1=a[1]*10+b[1]; 47 t2=b[1]*10+a[1]; 48 cmp(t1,t2); 49 return 0; 50 }
T2:逃亡(预期100 实际100)
题目大意:
在(xi,yi)中找到x或y的最短路
解析:
如题;
code
1 #include<cstdio> 2 using namespace std; 3 int n,m,k; 4 int x,y; 5 double sum=0; 6 int min(int a,int b) 7 { 8 if(a<b) 9 { 10 return a; 11 } 12 else 13 { 14 return b; 15 } 16 } 17 int main() 18 { 19 scanf("%d%d%d",&n,&m,&k); 20 for(int i=1;i<=k;i++) 21 { 22 scanf("%d%d",&x,&y); 23 int t1=min(x,n-x); 24 int t2=min(y,m-y); 25 sum+=min(t1,t2); 26 } 27 printf("%.3lf",sum); 28 return 0; 29 }
T3:数数字(预期20 实际20)
题目大意:
第i个蒟蒻会告诉你他看到了ai种数字(定义两个数字不同种当且仅当它们的值不同)
但是由于蒟蒻太弱了,可能会报错数据,NTF需要核实是否有一种情况使所有蒟蒻说的话都正确。
这是个题;
解析:
令总的卡片种类为 T,对于每一只蒟蒻,若它的卡片数值唯一则他所看到的卡片种类总
数为T-1,否则为T,我们称卡片数值唯一的蒟蒻是孤独的。
故若 ai 的最大值和最小值的差大于等于 2 则无解
下面对最大值和最小值的差进行分类讨论:
若 max=min,那么此时每只蒟蒻看到的卡片种类都为 T 或者都为 T-1。如果每只蒟蒻看到的
卡片种类的总数都是 T-1,则每只蒟蒻都是孤独的,此时 T=n。 否则每只蒟蒻所看到的卡片
种类的总数都是 T,由于不存在孤独的蒟蒻,所以 T 至多为⌊n/2⌊。
若 max=min+1,此时我们可以统计孤独的蒟蒻的个数 x,类似上面的推论, 数值总数至少为
x+1,至多为 x+⌊(n-x)/2⌊。故当 max=min+1 时, x+1≤T≤x+⌊(n-x)/2⌊
code
1 #include<cstdio> 2 #include<iostream> 3 using namespace std; 4 typedef long long ll; 5 int t; 6 int n; 7 int a[10000050]; 8 int only; 9 int sum; 10 //inline int read(){ 11 // char ch=getchar(); 12 // ll x=0; 13 // ll f=1; 14 // while(ch<'0'||ch>'9'){ 15 // if(ch=='-') 16 // f=-1; 17 // ch=getchar(); 18 // } 19 // while('0'<=ch&&ch<='9'){ 20 // x=x*10+ch-'0'; 21 // ch=getchar(); 22 // } 23 // return x*f; 24 //} 25 int main() 26 { 27 scanf("%d",&t); 28 while(t--) 29 { 30 scanf("%d",&n); 31 int maxn=-1; 32 int minm=2e9; 33 only=0; 34 sum=0; 35 for(int i=1;i<=n;i++) 36 { 37 scanf("%d",&a[i]); 38 if(maxn<a[i]) 39 maxn=a[i]; 40 if(minm>a[i]) 41 minm=a[i]; 42 } 43 for(int i=1;i<=n;i++) 44 if(a[i]==minm) only++; 45 if(maxn-minm>=2) 46 { 47 printf("no\n"); 48 continue; 49 } 50 if(minm==maxn) 51 { 52 if(maxn<=n/2||maxn+1==n) 53 { 54 printf("yes\n"); 55 continue; 56 } 57 printf("no\n"); 58 continue; 59 } 60 if(maxn==minm+1) 61 { 62 if(only+1<=maxn&&maxn<=(n-only)/2+only) 63 { 64 printf("yes\n"); 65 } 66 else 67 { 68 printf("no\n"); 69 } 70 } 71 } 72 return 0; 73 }
T4:tower(期望得分0 实际得分0);
题目大意:
欲穷千里目,更上一层楼。
阿克先生喜欢旅游。某一天,他来到魔法森林旅游。
经过观察,他发现魔法森林一共有n个城市,每个城市有一座高高的魔法塔,第i个城市的魔法塔的高度为hi。这些城市一共由n-1条道路连接,任意两座城市互相可达。
阿克先生想要站在某一座塔上观察尽可能多城市的风景。不幸的是,阿克先生没有透视眼,较高的塔将会遮蔽较低的塔。同时,魔法森林其他地方也被茂林覆盖,他的视线无法穿过茂林(但因为是魔法塔,塔上储存了镜面魔法,可以使阿克先生的视线在城市水平任意角度转弯)。
所以,他只能沿着n-1条道路观察其他的点。
但是,魔法森林的道路蜿蜒曲折,他观看的城市到他所在的点的路径要么互相包含要么两两不交。且从他所在的点开始,到任意它观察的城市,所成的高度序列单调不增。
阿克先生想要知道他最多能观察到多少个城市(包括自身),他快速地秒了这道题,但他懒得写代码了,所以请你帮他算一算。
解析:
30%
枚举阿克先生在哪个点,然后 dfs, 时间复杂度 O(n^2)。
20%链
从左往右扫一遍,从右往左扫一遍, 计算出每个点向左、向右最长不上升的长度, 然后加在
一起取 max 就是答案了。 时间复杂度 O(n)。
20%h 互不相同
观察到若 u 能够观察 v,则 v 一定不能观察 u, 所以按高度从小到大排序,依次加入,维护
每个点所能伸出的最长链即可; 或者可以直接记忆化搜索。 时间复杂度 O(n log n)或 O(n)。
100%
先固定一个点为根, 可以发现,答案的贡献被分为两类:子树内和子树外, dfs 一次,计算
出每个点在它子树内能延伸出的最长路径和次长路径,再计算每个点以他为所在节点在子树
内最多覆盖多少个点, 重新 dfs 一次,同时记录它往他父亲延伸最多能延伸多长, 每次向下
走一格,要么是原路径+1,要么是它兄弟的一个路径,取 max, 如果父亲>儿子,则伸向父
亲的长度清零, 每个节点的答案就是它子树内的答案+伸向他父亲的最长路径。 时间复杂度
O(n)
code
1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 using namespace std; 5 int tot=0; 6 int h[5000005]; 7 int s[5000005]; 8 int f[5000005],f1[5000005]; 9 int a[5000005]; 10 int ans=0; 11 struct edge { 12 int to,next; 13 } e[5000005]; 14 void add(int x,int y) { 15 e[++tot].to=y; 16 e[tot].next=h[x]; 17 h[x]=tot; 18 } 19 void dfs1(int u,int fa) { 20 s[u]=1,f[u]=1; 21 for(int i=h[u]; i!=0; i=e[i].next) { 22 int v=e[i].to; 23 if (v==fa) continue; 24 dfs1(v,u); 25 if (a[u]>=a[v]) { 26 if (f[u]<f[v]+1) { 27 f1[u]=f[u]; 28 f[u]=f[v]+1; 29 } else f1[u]=max(f1[u],f[v]+1); 30 s[u]+=f[v]; 31 } 32 } 33 } 34 void dfs2(int u,int fa,int up) { 35 ans=max(ans,up+s[u]); 36 for (int i=h[u]; i!=0; i=e[i].next) { 37 int v=e[i].to; 38 if (v==fa) continue; 39 if (a[v]<a[u]) 40 dfs2(v,u,0); 41 else { 42 if(f[v]+1==f[u]) 43 dfs2(v,u,max(up+1,f1[u])); 44 else 45 dfs2(v,u,max(up+1,f[u])); 46 } 47 } 48 } 49 int main() { 50 int n; 51 tot=0,ans=0; 52 scanf("%d",&n); 53 for (int i=1; i<=n; i++) 54 scanf("%d",&a[i]); 55 for (int i=1; i<n; i++) { 56 int q,p; 57 scanf("%d%d",&q,&p); 58 add(q,p),add(p,q); 59 } 60 dfs1(1,0); 61 dfs2(1,0,0); 62 printf("%d\n",ans); 63 }
最后附上oj链接:www.gdfzoj.com