比赛传送门
作者:WHy
签到题
G题 Lexicographical
题目大意
给一个数字n,输出1到n中字典序最大的那一个。
考察内容
字典序
分析
若除最后一位外全是9,输出其本身,否则输出len-1个9。
#include<bits/stdc++.h>
using namespace std;
int main(){
char s[1000010];
long len,i;
cin>>s;
len=strlen(s);
for(i=0;i<len;i++){
if(s[i]!='9')break;
}
if(i>=len-1){//除最后一位外全是9
cout<<s<<endl;
return 0;
}
for(i=0;i<len-1;i++){//其他情况
cout<<'9';
}
cout<<endl;
}
基本题
A题 Villages: Landines
题目大意
给定n个区间,求区间间隙之和
考察内容
排序
分析
按照左端点排序,然后从左到右枚举一遍,维护右端点并累加答案
#include<bits/stdc++.h>
#include<algorithm>
using namespace std;
const int N=2e5+10;
struct node{
long long l,r;
}a[N];
bool cmp(node x,node y){
if(x.l!=y.l)return x.l<y.l;
return x.r>y.r;
}
int main(){
int n;
long long xs,rs,ans=0,rr;
cin>>n;
for(int i=1;i<=n;i++){
cin>>xs>>rs;
a[i].l=xs-rs;
a[i].r=xs+rs;
}
sort(a+1,a+n+1,cmp);//将区间按左边界从小到大排序,左边界相同则按又边界从大到小排序
rr=a[1].r;
for(int i=2;i<=n;i++){//循环查找区间空隙
if(rr<a[i].l){//产生空隙,累加答案
ans+=a[i].l-rr;
rr=a[i].r;
}
else{
rr=max(rr,a[i].r);//不产生空隙,更新右边界
}
}
cout<<ans;
}
D题 Mocha and Railgun
题目大意
在圆内创建一宽度为2d的线段,将其沿垂直于其自身的一个方向延申,求其经过圆的弧长的最大值
考察内容
几何
分析
如图,当线段为直径的一部分时,可经过的弧长最大
#include<bits/stdc++.h>
using namespace std;
void solve(){
long long r,x,y,d;
double dis,ans,x1,x2,l,xita;
cin>>r>>x>>y>>d;
dis=sqrt((double)(x*x+y*y));
x1=sqrt(double(r*r)-(dis-d)*(dis-d));
x2=sqrt(double(r*r)-(dis+d)*(dis+d));
l=sqrt(double(4*d*d)+(x1-x2)*(x1-x2));
l/=2;
xita=asin(l/r);
ans=xita*2*r;
printf("%lf\n",ans);
}
int main(){
long long t;
cin>>t;
while(t--)solve();
return 0;
}
记得输出要换行,此题我们一个换行符调试了一个小时(所幸最后发现)
进阶题
C题 Grab the Seat
题目大意
求出满足由(0,1),(0,m)及一点(x,y)围成的三角形中没有已被占去位置的点的点(x,y)的个数
考察内容
几何,选择排序
分析
从下往上、从上往下各分析一遍每一列未被挡住的位置数
#include<bits/stdc++.h>
using namespace std;
const int N=200010;
int X[N],T1[N],T2[N];
int main(){
int n,m,k,q,px[N],py[N];
cin>>n>>m>>k>>q;
for(int i=1;i<=k;i++){
cin>>px[i]>>py[i];
}
while(q--){
int id;
cin>>id;
cin>>px[id]>>py[id];//更新座位
for(int i=1;i<=m;i++)X[i]=n+1;
for(int i=1;i<=k;i++)X[py[i]]=min(X[py[i]],px[i]);//取每行最左一个已被占的座位
for(int i=1,p=0;i<=m;i++){//从下往上扫描,p代表对第行列影响最大的行数
if(X[i]!=n+1&&(p==0||(long long)X[i]*(p-1)<(long long)X[p]*(i-1)))p=i;//整形相乘,强制转换为long long型以防爆内存。两式相乘为两式相除所得斜率表达式的变式
if(p==0)T1[i]=n;//暂无其他行影响第i行
else if(p==1){//p==1时,p-1为0,不能作除数,单独讨论
if(i==1)T1[i]=X[i]-1;
else T1[i]=n;
}
else{
int tmp=(long long)(i-1)*X[p]/(p-1);//求当前受其他行影响的第i行最右的好座位
if((long long)tmp*(p-1)==(long long)(i-1)*X[p])tmp--;//所求的好座位被本行的人占住
T1[i]=min(tmp,n);//防止超出教室
}
}
for(int i=m,p=0;i>=1;i--){//同上,从上往下再扫描一遍
if(X[i]!=n+1&&(p==0||(long long)X[i]*(p-m)>(long long)X[p]*(i-m)))p=i;
if(p==0)T2[i]=n;
else if(p==m){
if(i==m)T2[i]=X[i]-1;
else T2[i]=n;
}
else{
int tmp=(long long)(i-m)*X[p]/(p-m);
if((long long)tmp*(p-m)==(long long)(i-m)*X[p])tmp--;
T2[i]=min(tmp,n);
}
}
long long ans=0;
for(int i=1;i<=m;i++)ans+=min(T1[i],T2[i]);//生成答案
printf("%lld\n",ans);
}
return 0;
}