首页 > 其他分享 >AtCoder Beginner Contest 267 题解

AtCoder Beginner Contest 267 题解

时间:2022-09-07 21:57:57浏览次数:93  
标签:AtCoder ch 10 int 题解 read while 267 getchar

只会 \(A\sim G\)

主观难度:\(A<B<C<E<D<F<G<Ex\)

A - Saturday

分别对周一到周五判断即可。

#include<bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

string s;

int main(){
	cin>>s;
	if(s=="Monday")puts("5");
	else if(s=="Tuesday")puts("4");
	else if(s=="Wednesday")puts("3");
	else if(s=="Thursday")puts("2");
	else puts("1");
	return 0;
}

B - Split?

将十个数映射到长度为 \(7\) 的数组 \(t\) 中(因为一共有 \(7\) 列),判断是否编号为 \(1\) 的球倒了且 \(t[i]\) 列没全倒,\(t[i+1]\) 列全倒了,\(t[i+2]\sim t[7]\) 是否有没全倒的。

#include<bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

char a[11];
int t[10];

int main(){
	cin>>a+1;
	for(int i=1;i<=10;++i){
		if(a[i]=='1'){
			if(i==1||i==5)t[4]++;
			else if(i==2||i==8)t[3]++;
			else if(i==4)t[2]++;
			else if(i==7)t[1]++;
			else if(i==10)t[7]++;
			else if(i==6)t[6]++;
			else t[5]++;
		}
	}
	for(int i=1;i<=7;++i){
		if(t[i]&&!t[i+1]){
			for(int j=i+2;j<=7;++j){
				if(t[j]&&a[1]=='0'){
					puts("Yes");
					return 0;
				}
			}
		}
	}
	puts("No");
	return 0;
}

C - Index × A(Continuous ver.)

记 \(sum[i]=\sum\limits_{j=1}^ia_j,f[i]=\sum\limits_{j=1}^{m}j\times a_{i-m+j}\)。

考虑如何 \(O(1)\) 从 \(f[i-1]\) 转移到 \(f[i]\)。

\(f[i]=f[i-1]-(sum[i-1]-sum[i-1-m])+m\times a_i\)

取 \(f[m]\sim f[n]\) 的最大值即可。

#include<bits/stdc++.h>
using namespace std;

#define int long long

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=2e5+5;
int n,m,a[N],sum[N],f,ans=-1e18;

signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=read(),sum[i]=sum[i-1]+a[i];
	for(int i=1;i<=m;++i)f+=i*a[i];ans=f;
	for(int i=m+1;i<=n;++i)f=f-(sum[i-1]-sum[i-1-m])+m*a[i],ans=max(ans,f);
	print(ans);
	return 0;
}

D - Index × A(Not Continuous ver.)

设 \(f[i][j]\) 为在前 \(i\) 个数中选 \(j\) 个数,强制选 \(a[i]\) 的最大值。

我们发现这样转移是 \(O(n^3)\) 的,考虑优化,对于 \(i,j\),我们可以记录 \(f\) 的最大值,然鹅这样不太好。

重新设 \(f[i][j]\) 为在前 \(i\) 个数中选 \(j\) 个数,不强制选 \(a[i]\) 的最大值。

\(f[i][j]=\max(f[i-1][j],f[i-1][j-1]+j\times a_i)\)

#include<bits/stdc++.h>
using namespace std;

#define int long long

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=2e3+5;
int n,m,a[N],f[N][N];

signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=0;i<=n;++i)for(int j=1;j<=m;++j)f[i][j]=-1e18;
	for(int i=1;i<=n;++i){
		for(int j=1;j<=m;++j){
			f[i][j]=max(f[i-1][j],f[i-1][j-1]+a[i]*j);
		}
	}
	print(f[n][m]);
	return 0;
}

E - Erasing Vertices 2

考虑贪心,记 \(f(i)\) 为点 \(i\) 计算出来的值,我们从最小点值的点开始删,因为 \(f(i)\) 不会增大,所以这样一定是最优的。

  • 用一个 \(set\) 维护,需要注意的是,若 set<node>snode 重载运算小于号时,两个变量都需要考虑到。

这样写:

struct NODE{
	int num,w;
	bool operator<(const NODE &p)const{return w==p.w?num<p.num:w<p.w;}
};
set<NODE>s;

而不能这样写:

struct NODE{
	int num,w;
	bool operator<(const NODE &p)const{return w<p.w;}
};
set<NODE>s;
#include<bits/stdc++.h>
using namespace std;

#define int long long

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=2e5+5;
int n,m,a[N],head[N],cnt,f[N];
bool vis[N];
struct node{
	int to,next;
}e[N<<1];

void add(int from,int to){
	e[++cnt]={to,head[from]},head[from]=cnt;
}

struct NODE{
	int num,w;
	bool operator<(const NODE &p)const{return w==p.w?num<p.num:w<p.w;}
};
set<NODE>s;

signed main(){
	n=read(),m=read();
	for(int i=1;i<=n;++i)a[i]=read();
	for(int i=1;i<=m;++i){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	for(int i=1;i<=n;++i){
		for(int j=head[i];j;j=e[j].next){
			f[i]+=a[e[j].to];
		}
		s.insert({i,f[i]});
	}
	int ans=0,cnt=n;
	while(cnt--){
		int u=(*s.begin()).num;
		ans=max(ans,(*s.begin()).w);
		for(int i=head[u];i;i=e[i].next){
			int v=e[i].to;
			if(vis[v])continue;
			s.erase({v,f[v]});
			f[v]-=a[u];
			s.insert({v,f[v]});
		}
		s.erase({u,f[u]});
		vis[u]=1;
	}
	print(ans);
	return 0;
}

F - Exactly K Steps

这题排除一些不可做的想法之后,我们可以想到树的直径和将 \(k\) 分解倍增。

一种很麻烦的方法是,把一颗树拆分成一条直径,若能走到直径上,在直径上倍增即可;若不能走到直径上,从该点和直径上的最近点跳即可,需要很多的分类讨论以及细节。

  • 直接让直径的两个端点为根,各求一遍关于点 \(i\) 的 \(2^j\) 级祖先,直接求该点的 \(k\) 级祖先即可。
#include<bits/stdc++.h>
using namespace std;

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=2e5+5;
int n,q,head[N],cnt,a[N],num;
struct node{
	int to,next;
}e[N<<1];

void add(int from,int to){
	e[++cnt]=(node){to,head[from]},head[from]=cnt;
}

int dis[N],pre[N],L,R,lg[N],tmp;
bool vis[N];
int fl[N][21],fr[N][21],depl[N],depr[N],disl[N],disr[N];

void dfs(int x,int Fa){
	dis[x]=dis[Fa]+1;
	pre[x]=Fa;
	for(int i=head[x];i;i=e[i].next){
		int y=e[i].to;
		if(y==Fa)continue;
		dfs(y,x);
		if(dis[y]>dis[tmp])tmp=y;
	}
}

void get_d(){
	tmp=1;
	dis[0]=-1;
	dfs(1,0);
	L=tmp,dis[0]=-1;
	dfs(tmp,0);
	R=tmp,num=dis[R]+1;
}

void dfsL(int x,int fa){
	depl[x]=depl[fa]+1,fl[x][0]=fa;
	for(int i=1;i<=lg[depl[x]];++i)fl[x][i]=fl[fl[x][i-1]][i-1];
	for(int i=head[x];i;i=e[i].next){
		int y=e[i].to;
		if(y==fa)continue;
		dfsL(y,x);
	}
}

void dfsR(int x,int fa){
	depr[x]=depr[fa]+1,fr[x][0]=fa;
	for(int i=1;i<=lg[depr[x]];++i)fr[x][i]=fr[fr[x][i-1]][i-1];
	for(int i=head[x];i;i=e[i].next){
		int y=e[i].to;
		if(y==fa)continue;
		dfsR(y,x);
	}
}

int get_kth_fa_L(int x,int k){
	if(!k)return x;
	if((1<<lg[k])==k)return fl[x][lg[k]];
	return get_kth_fa_L(fl[x][lg[k]],k-(1<<lg[k]));
}

int get_kth_fa_R(int x,int k){
	if(!k)return x;
	if((1<<lg[k])==k)return fr[x][lg[k]];
	return get_kth_fa_R(fr[x][lg[k]],k-(1<<lg[k]));
}

int main(){
	n=read();
	for(int i=1;i<=n-1;++i){
		int u=read(),v=read();
		add(u,v),add(v,u);
	}
	get_d();
	for(int i=R;i;i=pre[i])vis[i]=1,a[num--]=i;
	for(int i=2;i<=n;++i)lg[i]=lg[i>>1]+1;
	num=dis[R]+1;
	depl[0]=depr[0]=-1;
	dfsL(L,0);
	dfsR(R,0);
	q=read();
	while(q--){
		int u=read(),k=read(),ans;
		if(depl[u]<k&&depr[u]<k)ans=-1;
		else if(depl[u]>=k)ans=get_kth_fa_L(u,k);
		else ans=get_kth_fa_R(u,k);
		print(ans),puts("");
	}
	return 0;
}

G - Increasing K Times

不妨从大到小放入,假设原来本就有两个数 \(\{0,0\}\) 我们在其中插入数,这样最后我们求的是恰好有 \(k+1\) 个。

记 \(f[i][j]\) 为插入前 \(i\) 小的数,使得有 \(j\) 个 \(a_p<a_{p+1}\) 的方案数。

分析一波在 \(a_p\) 和 \(a_{p+1}\) 之间插入的情况,发现只有 \(a_i>a_p\ge a_{p+1}\) 的情况,将 \(a_i\) 插入到 \(a_p\) 和 \(a_{p+1}\) 之间会使个数增加 \(1\),其余都是 \(0\)。

先排序一遍。

已放入 \(i-1\) 个数,之前有 \(cnt\) 个数与 \(a_i\) 相同。

\(f[i][j]=(j+cnt)f[i-1][j]+(i+1-j-cnt)f[i-1][j-1]\)

#include<bits/stdc++.h>
using namespace std;

#define int long long

inline int read(){
    int x=0,f=1;
    char ch=getchar();
    while(ch<'0'||ch>'9'){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9'){
        x=(x<<1)+(x<<3)+(ch^48);
        ch=getchar();
    }
    return x*f;
}

void print(int x){
	if(x<0)putchar('-'),x=-x;
	if(x>9)print(x/10);
	putchar(x%10^48);
}

const int N=5e3+5,mod=998244353;
int n,k,a[N],f[N][N],cnt;

signed main(){
	n=read(),k=read();
	for(int i=1;i<=n;++i)a[i]=read();
	sort(a+1,a+n+1);
	f[0][0]=1;
	for(int i=1;i<=n;++i){
		if(a[i]==a[i-1])cnt++;
		else cnt=0;
		for(int j=1;j<=min(k+1,i+1-cnt);++j){
			f[i][j]=(f[i-1][j]*(j+cnt)%mod+f[i-1][j-1]*(i+1-j-cnt)%mod)%mod;	
		}
	}
	print(f[n][k+1]);
	return 0;
}

标签:AtCoder,ch,10,int,题解,read,while,267,getchar
From: https://www.cnblogs.com/Daidly/p/16667401.html

相关文章

  • AtCoder Beginner Contest 262(D-E)
    D-IHateNon-integerNumber题意:一个长度为n的数组,选择其中的x项,问其中有多少种选择,这x项的和可以被选择的数目整除,比如,选择3个数,和为6,那么6/3=2,就可以被整除。题解:......
  • ABC #267 C、D、E、F
    C-Index×A(Continuousver.)(atcoder.jp)考虑维护一个长度为m的滑动窗口,滑动窗口从左往右移动的过程中,维护\(\sum_{i=1}^Mi*B_i\)。右端点往后移动一格到位置i,对......
  • CF1305F Kuroni and the Punishment 题解
    一道比较简单的题,我居然调了这么久。思路看一眼这个题,发现好像没有什么思路。考虑来用一些巧妙的手法,比如随机化。首先证明一个结论,至少有一半的数只会被操作一次或者......
  • CF1715E Long Way Home 题解
    CF1715E题解题意一个带边权无向图,可以沿着边走,需要边权的花费或从任意点\(u\)飞到\(v\),需要\((u-v)^2\)的花费。求从点\(1\)到所有\(i\)的最少花费。最多飞\(......
  • CF1515E Phoenix and Computers 题解
    感觉这样的\(\text{dp}\)题还比较多,思路都比较的神奇。个人感觉比较像区间\(\text{dp}\)的一类变种。但又和区间\(\text{dp}\)的维护方式极不一样。对于此类\(\t......
  • P5999 [CEOI2016] kangaroo 题解
    感觉这样的\(\text{dp}\)题还比较多,思路都比较的神奇。个人感觉比较像区间\(\text{dp}\)的一类变种。但又和区间\(\text{dp}\)的维护方式极不一样。对于此类\(\t......
  • AtCoder Regular Contest 147
    ProblemA题目大意:由N个正整数组成的序列,我们可以从中取出任意长短序列进行如下操作:序列中(最大值maxn%最小值minn=A),如果A为0则删除maxn,否则用A替换,询问要使得整个序......
  • MySQL5.7完整安装教程及相关问题解决
    1 下载安装1.1下载直接官网下载https://www.mysql.com/①拉倒最下面,点community server②选择之前的版本③选5.7,通过压缩包来安装,点download1.2解压安装①下......
  • AtCoder做题记录
    AtCoder大乱炖AtCoder乱做AtCoder随便草ARC147ARC147C发现这个式子当所有\(x_i\)趋近于某一个值时答案比较优,于是可以发现这是一个近似单谷函数,用二分+随机化/特......
  • CF222C Reducing Fractions 题解
    虽然是朴素的筛法,但是跑的比希儿的Pollard-rho快。\(\mathcalO(n\sqrtn)\)的质因数分解是不行的,Pollard-rho的码量也过于麻烦,直接在线性筛里筛出每个数的最小质因子......