A题
给出一个发电站和多个建筑物的一维坐标,需要通过电塔和电线将它们全部连接起来,实现所用电线长度最短。在发电站/建筑物半径范围内可以直接与电塔相连,电塔与电塔之间通过电线相连。其实可以很轻松的判断出是一道区间合并题。(虽然和队友讨论了很久......)
以下是本蒟蒻的代码。。。
#include <bits/stdc++.h>
using namespace std;
int n,lm,rm,p,l,ans,kl,kr;
struct op{
int x,y,l,r;};
op s[200005];
bool cmp(op a,op b)
{
if (a.l>b.l)
return false;
if (a.l<b.l)
return true;
else if (a.r<b.r)
return false;
return true;
}
int main()
{
scanf("%d",&n);
scanf("%d %d",&s[1].x,&s[1].y);
s[1].l=s[1].x-s[1].y;
s[1].r=s[1].x+s[1].y;
lm=s[1].x;rm=s[1].x;
for (int i=2;i<=n;i++){
scanf("%d %d",&s[i].x,&s[i].y);
if (s[i].x<lm)
lm=p;
if (s[i].y>rm)
rm=p;
s[i].l=s[i].x-s[i].y;
s[i].r=s[i].x+s[i].y;
}
sort (s+1,s+1+n,cmp);
int dis=0;
kl=s[1].l;kr=s[1].r;
for (int i=2;i<=n;i++){
if (s[i].r>kr)
kr=s[i].r;
dis=s[i+1].l-kr;
if (dis>0)
ans+=dis;
}
if (kl>lm)
ans+=kl-lm;
if (kr<rm)
ans+=rm-kr;
cout<<ans;
return 0;
}
但因为自己的粗心,少考虑了左边合并后,右边也得改区间,所以wa了2发,靠队友才过的wwwwww(队友太强了)
下面是队友大佬的代码,更好理解
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<bits/stdc++.h>
#include<algorithm>
#include<cmath>
#include<map>
#include<string>
#include<sstream>
#include<time.h>
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;
}
C题
结合图形可以更好理解题目,这里用一下其他大佬((Tan_Yuu))的图。
题目大概就是找出没有被覆盖的区域的点数量,观察图可以发现,被覆盖区域由两点斜线决定,斜率最大的斜线是被覆盖区域的上界,斜率最小的斜线是被覆盖区域的下界。可以通过两次遍历维护每行的好点数;对于每次遍历,我们只需要记录已遍历部分中斜率最大/最小的边界线,由其与此行的交点坐标限定此行的好点数。在维护边界线时,注意边界情况(斜率为0);两次遍历后,累加每行的好点数即可得到答案,每次查询的时间复杂度为O ( n ) 。
因为自己太拉了,比赛的时候没看这道题,队友直接AC了,被带飞了。
#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;
}
D题
没什么好讲的,就一道平面几何题目,看图像可以直接做出来(不会证明,但凭借高中数学基础可以轻松判断)
但比赛的时候大家心急了,就疯狂的尝试,然后wa了5发,后面发现这个结论,后悔的要死。
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<bits/stdc++.h>
#include<algorithm>
#include<cmath>
#include<map>
#include<string>
#include<sstream>
#include<time.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("%.14lf\n",ans);
}
int main(){
int t;
cin>>t;
while(t--)solve();
return 0;
}
G题
单纯签到,但我们还是先wa了两发(5555555~)
#include <iostream>
#include <cstring>
using namespace std;
#define int long long int
int main()
{
string s;
cin>>s;
int f=1;
int n=s.length();
if(n<=1)
{
cout<<s;
}
else
{
for(int i=0;i<n-1;i++)
{
cout<<"9";
if(s[i]!='9')
{
f=0;
}
}
if(f==1)
{
cout<<s[n-1];
}
}
return 0;
}
下面是补题...
I题
有一副麻将,初始给你13张牌(每张牌不超过2张),自己摸牌自己打,问预期要打多少个回合才能凑够七对牌。看大佬用概率dp,如果摸到的牌能够凑成一对,就留下,否则就丢掉。令dp[i][j]为当前手牌中有i张单牌,且剩余j张牌没摸时达成七对的数学期望,则有dp方程如下:
虽然没太看懂,但套用dp方程还是补过了这道题。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll km(ll a,ll b)
{
ll ans=1;
a%=mod;
while(b)
{
if(b&1)
ans=ans*a%mod;
a=a*a%mod;
b>>=1;
}
return ans;
}
ll dp[20][200];
ll dfs(ll x,ll sz)
{
if(x<=0||sz<3*x)return 0;
if(dp[x][sz])return dp[x][sz];
dp[x][sz]=(1+dfs(x-2,sz-1)*3*x%mod*km(sz,mod-2)%mod+dfs(x,sz-1)*(sz-3*x)%mod*km(sz,mod-2))%mod;
return dp[x][sz];
}
int tot=1;
void solve()
{
string s;
cin>>s;
map<string,int>mp;
int cnt=0;
for(int i=0;i<s.size();i+=2)
{
string s1="";
s1+=s[i];
s1+=s[i+1];
mp[s1]++;
if(mp[s1]==1)cnt++;
else cnt--;
}
cout<<"Case #"<<tot<<": "<<dfs(cnt,123)<<'\n';
tot++;
}
int main()
{
for(int i=0;i<=13;i++)
for(int j=0;j<=126;j++)
dp[i][j]=0;
int t;
cin>>t;
while(t--)
{
solve();
}
}
总结:
第一场我们的配合确实不太好,几乎大家都是自己写自己的,没怎么交流。希望之后可以更好一些吧。