AtCoder Beginner Contest 255 题解

只有 ABCDEFH 的题解。

A

模拟。

Code
const int N=10;
 
int n,m,a[N+10][N+10];
 
void mian(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=2;i++)
    for(int j=1;j<=2;j++)
      scanf("%d",a[i]+j);
  printf("%d\n",a[n][m]);
}

B

二分答案,暴力判断是否可行。

Code
const int N=1000;
 
int n,k,a[N+10],x[N+10],y[N+10];
 
ll dis(int i,int j){
  return 1LL*(x[i]-x[j])*(x[i]-x[j])+1LL*(y[i]-y[j])*(y[i]-y[j]);
}
 
bool check(ll r){
  for(int i=1;i<=n;i++){
    bool flg=0;
    for(int j=1;j<=k;j++){
      if(dis(i,a[j])<=r)flg=1;
    }
    if(!flg)return 0;
  }
  return 1;
}
 
void mian(){
  scanf("%d%d",&n,&k);
  for(int i=1;i<=k;i++)
    scanf("%d",a+i);
  for(int i=1;i<=n;i++)
    scanf("%d%d",x+i,y+i);
  ll l=0,r=1e18,ans=0;
  while(l<=r){
    ll mid=(l+r)>>1;
    if(check(mid))ans=mid,r=mid-1;
    else l=mid+1;
  }
  printf("%.6lf\n",std::sqrt(ans));
}

C

方便起见,如果 \(d<0\),则我们先把整个数列翻转一下。

分类讨论:\(x\le a_1\)\(x\ge a_n\)\(a_1\lt x\lt a_n\)

Code
void mian(){
  ll x,a,d,n;scanf("%lld%lld%lld%lld",&x,&a,&d,&n);
  if(d<0){
    a=a+(n-1)*d;
    d=-d;
  }
  if(x<=a)printf("%lld\n",a-x);
  else if(x>=a+(n-1)*d)printf("%lld\n",x-(a+(n-1)*d));
  else{
    if((x-a)%d==0)printf("%lld\n",0);
    else{
      ll k=(x-a)/d+1;
      printf("%lld\n",std::min(x-(a+d*(k-1)),a+d*k-x));
    }
  }
}

D

要求的就是 \(\sum_{i=1}^n|a_i-x|\)

先给 \(a\) 排序,每次询问二分“分界点”即可。

Code
const int N=2e5;
 
int n,m,a[N+10];
ll sum[N+10];
 
void mian(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<=n;i++)
    scanf("%d",a+i);
  std::sort(a+1,a+n+1);
  for(int i=1;i<=n;i++)
    sum[i]=sum[i-1]+a[i];
  while(m--){
    int x;scanf("%d",&x);
    if(x<=a[1])printf("%lld\n",sum[n]-1LL*n*x);
    else if(x>=a[n])printf("%lld\n",1LL*n*x-sum[n]);
    else{
      int p=std::lower_bound(a+1,a+n+1,x)-a;
      printf("%lld\n",1LL*(p-1)*x-sum[p-1]-1LL*(n-p+1)*x+(sum[n]-sum[p-1]));
    }
  }
}

E

观察一:如果确定了 \(a_1\sim a_n\) 中的某个数,那么整个 \(a\) 就确定了。

观察二:\(m\le 10\),可以枚举 \((i,j)\),计算当 \(a_i=x_j\) 时,\(a_1\) 应该是多少。同时此时的 \(a_1\) 给答案贡献了 \(1\)

可以用 std::map 统计观察二中提到的贡献。

Code
const int N=1e5;
 
int n,m;
ll s[N+10],x[15],a[N+10];
std::map<ll,int> mp;
 
void mian(){
  scanf("%d%d",&n,&m);
  for(int i=1;i<n;i++)
    scanf("%lld",s+i);
  for(int i=2;i<=n;i++)
    a[i]=s[i-1]-a[i-1];
  for(int i=1;i<=m;i++)
    scanf("%lld",x+i);
  for(int i=1;i<=n;i++)
    for(int j=1;j<=m;j++){
      if(i&1)mp[x[j]-a[i]]++;
      else mp[a[i]-x[j]]++;
    }
  int ans=0;
  for(auto p:mp)
    ans=std::max(ans,p.second);
  printf("%d\n",ans);
}

F

初赛题……

以前一直都是在草稿纸上算,今天终于要在计算机上算了(

Code
const int N=2e5;
 
int n,a[N+10],b[N+10],pos[N+10],ptr;
int L[N+10],R[N+10];
 
int solve(int l,int r){
  if(l==r){
    if(pos[a[++ptr]]!=l){
      puts("-1");
      exit(0);
    }
    return a[ptr];
  }
  int rt=a[++ptr],p=pos[rt];
  if(l<=p-1)L[rt]=solve(l,p-1);
  if(p+1<=r)R[rt]=solve(p+1,r);
  return rt;
}
 
void mian(){
  scanf("%d",&n);
  for(int i=1;i<=n;i++)
    scanf("%d",a+i);
  for(int i=1;i<=n;i++)
    scanf("%d",b+i),pos[b[i]]=i;
  if(a[1]!=1)return puts("-1"),void();
  solve(1,n);
  for(int i=1;i<=n;i++)
    printf("%d %d\n",L[i],R[i]);
}

H

考虑哪些修改对某次询问有贡献,那我们要算的就是最后一次覆盖后的和,也就是总的和减去最后一次覆盖前的和。

可以用线段树维护区间最后被覆盖时的区间和 \(sum\),于是询问 \((d,l,r)\) 的答案为 \(d\left(\sum_{i=l}^ri\right)-sum\)

Code
const int N=2e5;
const int P=998244353,inv=(P+1)/2;
 
struct Node{
  ll sum,atag;
  int ls,rs;
};
 
Node t[40000005];
ll n;
int m,tott,root;
 
ll calc(ll l,ll r){
  return ((l+r)%P)*((r-l+1)%P)%P*inv%P;
}
 
#define ls(x) (t[x].ls)
#define rs(x) (t[x].rs)
 
void pushUp(int i){
  t[i].sum=(t[ls(i)].sum+t[rs(i)].sum)%P;
}
 
void pushA(int i,ll l,ll r,ll atag){
  t[i].sum=calc(l,r)*(atag%P)%P;
  t[i].atag=atag;
}
 
void pushDown(int i,ll l,ll r){
  if(t[i].atag){
    ll mid=(l+r)>>1;
    if(!ls(i))ls(i)=++tott;
    if(!rs(i))rs(i)=++tott;
    pushA(ls(i),l,mid,t[i].atag);
    pushA(rs(i),mid+1,r,t[i].atag);
    t[i].atag=0;
  }
}
 
void modify(int &i,ll l,ll r,ll ql,ll qr,ll x){
  if(!i)i=++tott;
  if(ql<=l&&r<=qr)return pushA(i,l,r,x),void();
  ll mid=(l+r)>>1;
  pushDown(i,l,r);
  if(ql<=mid)modify(ls(i),l,mid,ql,qr,x);
  if(qr>mid) modify(rs(i),mid+1,r,ql,qr,x);
  pushUp(i);
}
 
ll query(int i,ll l,ll r,ll ql,ll qr){
  if(!i)return 0;
  if(ql<=l&&r<=qr)return t[i].sum;
  ll mid=(l+r)>>1,res=0;
  pushDown(i,l,r);
  if(ql<=mid)(res+=query(ls(i),l,mid,ql,qr))%=P;
  if(qr>mid) (res+=query(rs(i),mid+1,r,ql,qr))%=P;
  return res;
}
 
#undef ls
#undef rs
 
void mian(){
  scanf("%lld%d",&n,&m);
  while(m--){
    ll d,l,r;
    scanf("%lld%lld%lld",&d,&l,&r);
    ll ans=calc(l,r)*(d%P)%P;
    (ans-=query(root,1,n,l,r))%=P;
    printf("%lld\n",(ans+P)%P);
    modify(root,1,n,l,r,d);
  }
}
posted @ 2022-06-11 23:05  registerGen  阅读(385)  评论(0)    收藏  举报