首页 > 其他分享 >Educational Codeforces Round 138

Educational Codeforces Round 138

时间:2022-10-22 14:12:31浏览次数:98  
标签:Educational int cin Codeforces pb color 138 id define

Educational Codeforces Round 138

这把是真的丢了大脸。

Dashboard

$\color{Green}{★}\ \ $ 表示赛时做出。
$\color{Yellow}{★}\ \ $ 表示赛后已补。
$\color{Red}{★}\ \ $ 表示 \(\mathcal{To\ be\ solved}\)。

A

A. Cowardly Rooks

\(\color{Green}{★}\ \ \mathcal{*Difficulty: ?}\)

Description

\(n \times n\) 的棋盘,有 \(m\) 原本不会互相攻击的车,询问是否能移动一辆车且依然不会互相攻击。

Solution

显然,只要 \(m \ne n\),就必然有解。

code
void work(){
  int n,m;cin>>n>>m;
  cout<<((n^m)?"YES\n":"NO\n");
}

B

B. Death's Blessing

$\color{Green}{★}\ $ \(\ \mathcal{*Difficulty: ?}\)

Description

\(n\) 个怪物,血量等于数组 \(a\),被打死时给相邻怪物回 \(b_i\) 的血,求最少要打的血量。

Solution

显然,只要无限壁咚边缘的怪,并把 \(b\) 中的最大值留到最后,就能使 \(b\) 数组造成的贡献最小。

最终答案为:\(\sum_{i=1}^n a_i+b_i - \max{b_i} (1 \le i \le n)\)

code
void work(){
  int n;cin>>n;vi a(n),b(n);
  L(i,0,n-1) cin>>a[i];L(i,0,n-1) cin>>b[i];
  int ans=0;L(i,0,n-1) ans+=a[i]+b[i];
  ans-=*max_element(all(b));cout<<ans<<'\n';
}

C

C. Number Game

$\color{Yellow}{★}\ $ \(\ \mathcal{*Difficulty: ?}\)

Description

对给定数组进行 \(k\) 轮的游戏,在第 \(i\) 轮时,A 取走一个小于等于 \(k-i+1\) 的数字,B 对一个数加上 \(k-i+1\),问 \(k\) 的最大值。

Solution

首先,不难看出,在第 \(i\) 轮,无论 \(B\) 对什么数进行加,都能使被加的数在后面的轮次无法被删除。

所以对于 \(B\),最佳决策就是从小开始操作数,对于 \(A\),自然就是从大数开始删,每次选最大的满足条件的数删去即可。

因为 \(n \le 100\),所以完全可以模拟整个过程,时间复杂度 \(O(n^3)\)。

当然,因为满足单调性,所以可以二分答案,时间复杂度 \(O(n^2 \log_2n)\)。

code
bool sol(int k){
  b.resize(n);
  L(i,0,n-1) b[i]=a[i];
  L(i,1,k){
    int g=-1;R(j,n-1,0)
      if(b[j]<=k-i+1&&(b[j]!=-1)){
        g=b[j];b[j]=-1;break;
      }
    if(g==-1) return 0;
    for(int &i:b) if(~i){i=-1;break;}
  }return 1;
}void work(){
  cin>>n;a.resize(n);
  for(int &i:a) cin>>i;
  sort(all(a));
  L(i,0,n)
    if(sol(i)) s=i;
    else break;
  cout<<s<<'\n';
}

D

D. Counting Arrays

$\color{Yellow}{★}\ $ \(\ \mathcal{*Difficulty: ?}\)

Description

对于数组 \(a\) 中所有元素,如果满足 \(\gcd(a_i,i)=1\),就可以删除 \(a_i\),然后更新后面元素的下标。

给定数组大小 \(n\) 和数大小范围 \(m\),求问数组大小在 \([1,n]\) 范围内,所有元素在 \([1,m]\) 范围内,能用不止一种方式删光整个数组的数组数量。

Solution

首先,无论数组如何,都能够无限删除第一个元素。

如果这是唯一的删除方法,那么其元素 \(a_i\) 必须满足:\(\gcd(a_i,j) \ (2\le j \le i)\),因为在下标改变的过程中,会从 \(i\) 逐步移动到 \(1\),一直不能删就只能一直互质。

所以,能够满足只有单一删除方式的数组中元素 \(i\) 的取值种类有

\[\left\lfloor \dfrac{m}{\prod_{j=2}^i j \cdot \text{isPrime}_j}\right\rfloor \]

之后就是统计答案,每次加上全排列数,然后减去每个位置的满足单一删除的数值之积。

如果用了快速幂之类的算法统计答案,时间复杂度就是 \(O(n \log_2 n)\)。

如果预处理出幂表,就能做到 \(O(n)\) 的时间复杂度。

下面给出的是 \(O(n)\) 做法,仅展示核心代码。

code
signed main(){
  FST;cin>>n>>m;prime_(n);
  a.resize(n+1);a[0]=1;
  L(i,1,n) a[i]=a[i-1]*m;
  L(i,1,n){
    if(isp[i]) g*=i;lst*=m/g;
    ans+=a[i]-lst;
  }cout<<ans;
}//用了封装的 modint

E

E. Cactus Wall

$\color{Yellow}{★}\ $ \(\ \mathcal{*Difficulty: ?}\)

Description

在 \(n \times m\) 的网格图中,加入一些障碍且所有障碍两两不相邻(四联通),原本已有一些障碍,求问是否能构造出一种障碍方案,使得不存在从第一行到最后一行的路径。

Solution

我的思路有点偏向于网络流。

”不存在路径“的要求就像网络流中的最小割,用障碍将图拦腰截断就行。

考虑建图,先标记所有原本已有的障碍的四联通,因为这些点是不能放障碍的。

然后对所有未被标记的点进行连边,因为障碍不能相邻,所以每个点对周围的四个角连边,边权由目标点是否原本有障碍决定。

然后像网络流那样引入一个源点和汇点。

源点向第一列的未标记点连边,最后一列的未标记点向汇点连边。

之后就可以跑 01BFS 或者 Dijskra,如果汇点的距离不为无穷大说明有解。

至于输出方案,就要记录路径,并将路径上的点记录并输出即可。

时间复杂度:\(O(n m \log_2 n m)\)

code
#include <bits/stdc++.h>
using namespace std;
#define F(i) (i).first
#define S(i) (i).second
#define si(i) ((int)i.size())
#define pb push_back
#define vi vector<int>
#define pi pair<int,int>
#define id(x,y) (x*m+y)
#define all(x) (x).begin(),(x).end()
#define me(t,x) memset(t,x,sizeof(t))
#define L(i,j,k) for(int (i)=(j);i<=(k);(i)++)
#define R(i,j,k) for(int (i)=(j);i>=(k);(i)--)
#define FST ios::sync_with_stdio(0);cin.tie(0);

const int N=5e5+100,INF=1e9;

int n,m,st,ed,pre[N],dis[N];
bool vis[N];vector<bool>b[N];vector<pi>g[N];
vector<pi>d={{-1,0},{1,0},{0,-1},{0,1}};
vector<pi>k={{-1,-1},{1,1},{1,-1},{-1,1}};
void work(){
  cin>>n>>m;
  st=n*m;ed=n*m+1;
  vector<string>s(n);
  L(i,0,n) b[i].resize(m+1);
  L(i,0,n) fill(all(b[i]),0);
  L(i,0,ed) g[i].clear();
  for(auto &i:s) cin>>i;
  L(i,0,n-1) L(j,0,m-1)
    if(s[i][j]=='#')
      for(pi x:d){
        int p=i+F(x),q=j+S(x);
        if(p<0||q<0||p>=n||q>=m) continue;
        b[p][q]=1;
      }
  L(i,0,n-1) L(j,0,m-1) if(!b[i][j])
    for(pi x:k){
      int p=i+F(x),q=j+S(x);
      if(p<0||q<0||p>=n||q>=m||b[p][q]) continue;
      g[id(i,j)].pb({id(p,q),s[p][q]=='.'});
    }
  L(i,0,n-1) if(!b[i][0]) g[st].pb({id(i,0),s[i][0]=='.'});
  L(i,0,n-1) if(!b[i][m-1]) g[id(i,m-1)].pb({ed,0});
  fill(dis,dis+n*m+5,INF);
  fill(vis,vis+n*m+5,0);
  fill(pre,pre+n*m+5,0);
  deque<int>q;
  q.push_back(st),dis[st]=0;
  while(!q.empty()){
    int u=q.front();q.pop_front();
    if(vis[u]) continue;vis[u]=1;
    for(pi x:g[u]){
      if(dis[F(x)]<=dis[u]+S(x)) continue;
      dis[F(x)]=dis[u]+S(x);pre[F(x)]=u;
      if(!S(x)) q.push_front(F(x));
      else q.push_back(F(x));
    }
  }if(dis[ed]==INF) return cout<<"NO\n",void();
  cout<<"YES\n";
  for(int i=ed;i^st;i=pre[i]) 
    if(i<n*m) s[i/m][i%m]='#';
  for(auto i:s) cout<<i<<'\n';
}signed main(){
  FST;int t;cin>>t;
  L(i,1,t) work();
}

F

F. Distance to the Path

$\color{Yellow}{★}\ $ \(\ \mathcal{*Difficulty: ?}\)

Description

给定一棵有 \(n\) 个节点的树,每个点有点权,初始全为 \(0\),进行 \(m\) 次操作,操作分两种:

  1. 输出给定节点 \(v\) 的权值。

  2. 给定节点 \(u,v\),权值 \(k\),距离 \(d\),对所有距离 \(u,v\) 之间的简单路径小于等于 \(d\) 的点的权值加上 \(k\)

Solution

暂时咕着。

code
#include <bits/stdc++.h>
using namespace std;
#define lb(x) (x&-x)
#define pb push_back
#define vi vector<int>
#define pi pair<int,int>
#define L(i,j,k) for(int (i)=(j);i<=(k);(i)++)
#define FST ios::sync_with_stdio(0);cin.tie(0);
const int N=2e5+100;
int n,m,tot,u,v,x,r;vi g[N];
int id[N],f[N],h[N],d[N],si[N],t[N],a[N],b[N];
struct BIT{
  int c[N];void add(int x,int k){for(;x<=n;x+=lb(x)) c[x]+=k;}
  int ask(int x){int s=0;for(;x;x-=lb(x)) s+=c[x];return s;}
}T[21];
void dfs1(int u,int fa){
  f[u]=fa;si[u]=1;d[u]=d[fa]+1;
  for(int v:g[u]) if(v^fa){
    dfs1(v,u);si[u]+=si[v];
    if(si[h[u]]<si[v]) h[u]=v;
  }
}void dfs2(int u,int tp){
  t[u]=tp;id[u]=++tot;
  if(!h[u]) return ;dfs2(h[u],tp);
  for(int v:g[u]) if(v^f[u]&&v^h[u]) dfs2(v,v);
}int lca(int x,int y){
  while(t[x]^t[y])
    if(d[t[x]]<d[t[y]]) y=f[t[y]];
    else x=f[t[x]];return d[x]<d[y]?x:y;
}void change(int u,int v,int k,int x){
  while(t[u]^t[v]){
    if(d[t[u]]<d[t[v]]) swap(u,v);T[x].add(id[t[u]],k);
    T[x].add(id[u]+1,-k);u=f[t[u]];
  }if(d[u]>d[v]) swap(u,v);
  T[x].add(id[u],k);T[x].add(id[v]+1,-k);
}int main(){
  FST;cin>>n;L(i,1,n-1)
    cin>>u>>v,g[u].pb(v),g[v].pb(u);
  L(i,n+1,n+19) g[i].pb(i+1),g[i+1].pb(i);
  g[n+1].pb(1);g[1].pb(n+1);n+=20;
  dfs1(n,n);dfs2(n,n);cin>>m;
  L(i,1,m){
    int o,u,v,k,x;cin>>o;
    if(o==1){
      cin>>x;int g=0;L(j,0,20) 
        g+=T[j].ask(id[x]),x=f[x];
      cout<<g<<'\n';
    }else{
      cin>>u>>v>>k>>x;change(u,v,k,x);
      if(!x) continue;u=lca(u,v);
      change(u,u,-k,x);int g=0;
      L(j,0,x){
        L(p,0,x-j) change(u,u,k,p);
        if(g&&(j^x)) L(p,0,x-j-1)
          change(g,g,-k,p);
        g=u;u=f[u];
      }
    }
  }
}

最近一直在下分,希望中国场能上回来点吧。

标签:Educational,int,cin,Codeforces,pb,color,138,id,define
From: https://www.cnblogs.com/AIskeleton/p/16815050.html

相关文章

  • Codeforces 823B
    题意:对若干正整数二元组\((x_i,t_i)\),求一个实数\(x_0\),使得\(max\{t_i+|x_i-x_0|\}\)最小。n<=1e5。思考:​ 虽然问的是\(x_0\),但不妨对这个最小的最大值进行二分,也......
  • Educational Codeforces Round 138 (Rated for Div. 2) A-E
    比赛链接A题解知识点:贪心。注意到\(m\geqn\)时,不存在某一行或列空着,于是不能移动。而\(m<n\)时,一定存在,可以移动。时间复杂度\(O(1)\)空间复杂度\(O(1)\)代......
  • Dashboard - Educational Codeforces Round 138 (Rated for Div. 2) - Codeforces
    Dashboard-EducationalCodeforcesRound138(RatedforDiv.2)-Codeforces这场比赛写的就很菜了。D题有点思路但是没想到是求是去求不满足条件的序列。1.Problem......
  • Codeforces Round #828 (Div. 3)
    CodeforcesRound#828(Div.3)1.Problem-D-Codeforces只要找有因子2的个数即可。只要因子个数是大于等于n的即可。voidslove(){cin>>n;fel(i,1,n)cin......
  • Codeforces Round #756 (Div. 3) E1
    E1.EscapeTheMaze(easyversion)我们显然遍历根节点到叶结点的同时维护最短距离然后在return的时候看该点距离是否大于最近的朋友的距离要是大于的话我们显然可以......
  • Heidi and Library (hard) | CodeForces 802C最大流最小费用
    神仙题,想了两节ds课没想出来,跑到奇怪的犄角旮旯去了还是没法搞一个满意的模型看了洛谷黑题啊..释然了思路和细节在代码//LUOGU_RID:90857083#include<bits/stdc++.h......
  • Codeforces Round #760 E
    E.Singers'Tour我们显然可以推式子b[i]=a[i]+2a[i+1]+3a[i+1]....b[i+1]=na[i]+a[i+1]+2a[i+2]....这样b[i+1]-b[i]=-n*a[i]+(a[i]+a[i+1]+....+a[n])我们显然......
  • Educational Codeforces Round 83 (Rated for Div. 2) C. Adding Powers(进制转换)
    https://codeforces.com/contest/1312/problem/C题目大意:给定一个长度为n的数组a,在给定一个底数k。一开始数组元素全部都是0,我们每一个时间i可以选择一个下标下的数字......
  • Educational Codeforces Round 138 (Rated for Div. 2) ABC(二分)
    只能说这场的出题人不适合我食用,ABC都读了假题,离谱啊~A.CowardlyRooks题目大意:给定一个棋盘n*n的大小,左下角的顶点在(1,1);给定了棋盘格上的m个棋子坐标。这m个棋子......
  • 「题解」Codeforces 1730F Almost Sorted
    给定一个长度为\(n\)的置换\(p\),以及一个正整数\(k\).对于一个置换\(q\),要求对于所有满足\(1\leqi<j\leqn\)的\(i,j\),有以下不等式成立:\[p_{q_i}\leqp_{q_j}+......