2022牛客多校联赛第一场 题解

比赛传送门
作者: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;
} 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值