第二次ACM,感觉被虐了
尽管有大佬:慕容宝宝和 chhokmah的带领,还是感觉被虐了
一共13道,A了5道签到题,其中一道浪费了两个小时,然后就封榜了,然后就没有然后了………………
比赛题目一览:
A:Little Sub and Applese
B:Little Sub and Triples
C:Little Sub and Sequence
D:Little Sub and Balloons
E:Little Sub and Traveling
F:Little Sub and Game
G:Little Sub and Piggybank
H:Little Sub and Counting
I:Little Sub and Enigma
J:Little Sub and Apples
K:Little Sub and Triangles
L:Little Sub and AA
M:Little Sub and Johann
翻开试题一道这样的题映入眼帘:A
吼哈哈,这也太简单了吧,就是把句子的最后一个句号改成叹号
chhokmah随手打下了代码,WA……
原因:scanf不读空格
chhokmah又随手打下了代码,WA……
原因:gets不能用EOF
弃赛的念头涌上心头,然后破罐子破摔地乱改乱交的几次,听取WA声一片……
最终慕容宝宝逆转乾坤,AC!!!
额,A了一道签到题,我们的罚时已经多得不得了了
A题:AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
char s[1000005];
int main(){
while(gets(s)){
if (s[strlen(s)-1]=='.') s[strlen(s)-1]='!';
puts(s);
}
return 0;
}
然后看一下rank,发现D题和J题两条原谅色,然后开始我想D,慕容宝宝想J
5min后……
杨子曰:D题就是给你n个数,问你n个数中有几个不同的数,如此简单
慕容宝宝曰:J题就是给你n,k,t,求max(0,n-k*t),如此简单
只看chhokmah劈里啪啦,double AC!!开心啊啊!!!
D题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int n,ans=0;
map<int,int> mp;
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
int x;
scanf("%d",&x);
if (!mp[x]) ans++,mp[x]=1;
}
cout<<ans;
return 0;
}
J题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
int n,k,t;
int main(){
scanf("%d%d%d",&n,&k,&t);
long long ans=max((long long)0,(long long)n-(long long)k*t);
cout<<ans;
return 0;
}
然后再看下rank,哦,B题和H题是新大陆啊
先看下B题:什么还有自然对数的吗??仔细一看好吧条件4其实就是
A
x
+
A
y
>
A
z
A_x+A_y>A_z
Ax+Ay>Az,哦那不就是可以构成三角形的意思吗?所以说题目就是:给你一个序列,对于每个询问l,r,问该序列[l,r]区间内有没有三个数满足三角形三边关系
左想右想,依然没有思路,所以我们 毫无进取精神 知难而退,就果断放弃了
比赛结束后,看下题解,发现B题就是个暴力题,为神马呢?暴力的想法是对区间排序后,暴力查看相邻的三个数能不能满足条件,如果一直不满足,也就是a[i]+a[i+1]<=a[i+2]也就是说这个序列的增长速度,至少是斐波那契数列的增长速度,打个表后发现,斐波那契数列第56项就炸int了,所以当区间长度大于60时直接输出YES,其他情况就直接暴力呗,So,最终复杂度O(q*60 log 60)
B题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=200005;
int n,q;
long long a[maxn],x[maxn];
int main(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++){
scanf("%lld",&a[i]);
}
while(q--){
int l,r;
scanf("%d%d",&l,&r);
if (r<l+2 || l<1|| r>n ) printf("NO\n");
else if (r-l>=60) printf("YES\n");
else{
for (int i=l;i<=r;i++){
x[i]=a[i];
}
sort(x+l,x+r+1);
int flag=0;
for (int i=l;i<=r-2;i++){
if (1LL*(x[i]+x[i+1])>x[i+2]){
printf("YES\n");
flag=1;
break;
}
}
if (!flag) printf("NO\n");
}
}
return 0;
}
回到比赛现场
放弃了B题后果断来到了H题,题目很好理解,就是给你一个序列A,对于每一项
A
i
A_i
Ai输出有多少个
A
j
A_j
Aj满足
A
i
A
j
>
A
j
A
i
A_i^{ A_j}>A_j^{ A_i}
AiAj>AjAi,慕容宝宝认为对于
a
b
a^b
ab和
b
a
b^a
ba这样的两个数底数大的数大,然后我随手举了个反例
2
100
2^{100}
2100和
10
0
2
100^2
1002,慕容宝宝:……
我提出:指数大的数大,慕容宝宝随手一个反例
2
3
2^3
23和
3
2
3^2
32,我:……
欧,如果把我们两个的想法融合一下会发现如下结论:
对于1,答案永远是0
对于2,3是特例特殊判断
而后面的情况则是指数的的数大
所以排序后搞一搞,完事,chhokmah随手打完了代码,AC!
H题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
const int maxn=100005;
struct S{
int x,id;
}a[maxn];
int ans[maxn];
int n;
map<int,int> mp;
int cmp(S a,S b){
return a.x<b.x;
}
int main(){
scanf("%d",&n);
for (int i=1;i<=n;i++){
scanf("%d",&a[i].x);
mp[a[i].x]++;
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
int sum=0;
for (int i=1;i<=n;i++){
if (a[i].x==1) ans[a[i].id]=0;
else if (a[i].x!=a[i-1].x){
sum+=mp[a[i].x];
ans[a[i].id]=n-sum;
}
else{
ans[a[i].id]=ans[a[i-1].id];
}
}
for (int i=1;i<=n;i++){
if (a[i].x==2) ans[a[i].id]-=mp[3]+mp[4];
else if (a[i].x==3) ans[a[i].id]+=mp[2];
}
for (int i=1;i<=n;i++){
cout<<ans[i]<<' ';
}
return 0;
}
至此,我们A了4道题了,然而时间只过去了1个小时,粗略一算,我们3个半小时就可以AK了,哈哈哈哈,想法是美好的,现实是残酷的:
于是我们又来到了K题
就是说给你n个点,q个询问,对于每个询问l,r,求有多少个由这些点构成的三角形面积在[l,r]内。
嗯,先算算n个点最多可以构成多少给三角形:欧,2573000个,蛮好的,不仅存得下,而且排序也不会炸,然后就是看[l,r]区间内有多少个数了,那不就是二分吗!!!!!!
chhokmah问:三角形的面积怎么算?
杨子曰:看我的博客:海伦公式的证明——杨子曰数学
chhokmah:滚 欧,懂了懂了
然后开始打代码,不错不错,样例过了,交,WA
(然后中间又破罐子破摔了几次)
100min过去了
就在放弃的那一刹那,我突然试出了一组错误样例:
5 1
2 2
1 1
0 0
-1 -1
-2 -2
0 0
把面积输出来看看,居然有nan,显然是对负数开根了,可恶的精度误差
加个abs
又wa了,显然又是精度误差
然后又对区间左边开大0.1,右边开大0.1,AC!!!!!!!
终于,这道题花了我们两个小时,终于AC了,不久就封榜了
K题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
const int maxn=255;
int n,q;
double x[maxn],y[maxn],s[8000005];
double sqr(double x){
return x*x;
}
double dis(int i,int j){
return sqrt(sqr(x[i]-x[j])+sqr(y[i]-y[j]));
}
double sqrtt(double x){
return sqrt(abs(x));
}
double calc(double a,double b,double c){
return sqrtt((a+b+c)/2.0)*sqrtt((-a+b+c)/2.0)*sqrtt((a-b+c)/2.0)*sqrtt((a+b-c)/2.0);
}
int main(){
scanf("%d%d",&n,&q);
for (int i=1;i<=n;i++){
scanf("%lf%lf",&x[i],&y[i]);
}
int num=0;
for (int i=1;i<=n-2;i++){
for (int j=i+1;j<=n-1;j++){
for (int k=j+1;k<=n;k++){
s[++num]=calc(dis(i,j),dis(i,k),dis(j,k));
}
}
}
sort(s+1,s+num+1);
while (q--){
double l,r;
scanf("%lf%lf",&l,&r);
int d1=lower_bound(s+1,s+num+1,l-0.01)-s;
int d2=upper_bound(s+1,s+num+1,r+0.01)-s;
printf("%d\n",d2-d1);
}
return 0;
}
再看下排名,我们又到了I题
看下样例,哈哈哈哈哈哈哈,如此简单,不就是上下对应吗!为什么只有如此少的人A
随手一打,WA
从上面到下面一一对应,从下面到上面也要一一对应
WA
难道说,相同的字母不能对应?
WA
难道说,一个字母变成另一个字母,还可以继续变,所以要判环?
WA
……
我们的罚时飞速上升,于是比赛结束了我们也没有A掉这道题,一定是题目没看懂(←论英语的重要性)
看了题解,我惊了,这道题其实只有3个要求:
- 从上到下要一一对应
- 从下到上要一一对应
- 如果25个字母已经有了一一对应的关系,那么可以推理出第26个字母的对应关系,也要输出!!!!!
这…我无言以对
I题AC代码:
#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<map>
using namespace std;
char s1[1000005],s2[1000005];
int d1[30],d2[30];
int main(){
memset(d1,0,sizeof(d1));
memset(d2,0,sizeof(d2));
gets(s1);
gets(s2);
int n=strlen(s1)-1;
for (int i=0;i<=n;i++){
int k1=s1[i]-'a'+1;
int k2=s2[i]-'a'+1;
if (d1[k1] && d1[k1]!=k2){
cout<<"Impossible";
return 0;
}
if (!d1[k1]) d1[k1]=k2;
if (d2[k2] && d2[k2]!=k1){
cout<<"Impossible";
return 0;
}
if (!d2[k2]) d2[k2]=k1;
}
int num=0;
for (int i=1;i<=26;i++){
if (!d1[i]) num++;
}
if(num==1){
int k1,k2;
for (int i=1;i<=26;i++){
if (!d1[i]) k1=i;
if (!d2[i]) k2=i;
}
d1[k1]=k2;
d2[k2]=k1;
}
for (int i=1;i<=26;i++){
// cout<<i<<' '<<d1[i]<<endl;
if (!d1[i]) continue;
printf("%c->%c\n",i+'a'-1,d1[i]+'a'-1);
}
return 0;
}
于是比赛结束了,5道AC,还可以吧,但 I题把我们虐待太惨了…
88
比赛其他的题目将持续更新……
于HG机房