AtCoder Beginner Contest 360 - VP记录

A - A Healthy Breakfast

高桥日常出境。

头一次知道 getchar() 的返回值是 int

点击查看代码
#include<cstdio>
using namespace std;

int main()
{
	char s[3]={getchar(),getchar(),getchar()};
	     if(s[0]=='R'&&s[1]=='M') puts("Yes");
	else if(s[0]=='R'&&s[2]=='M') puts("Yes");
	else if(s[1]=='R'&&s[2]=='M') puts("Yes");
	else puts("No");
	return 0;
}

B - Vertical Reading

题目可以转化成从 \(c\) 开始,每次跳 \(w\) 个字符。

所以直接枚举 \(c\)\(w\) + 暴力判断。

点击查看代码
#include<cstdio>
#include<cstring>
using namespace std;

const int N=105;
int n,m;
char s[N],t[N];

int main()
{
	scanf("%s%s",s+1,t+1);
	n=strlen(s+1),m=strlen(t+1);
	for(int w=1;w<n;w++)
		for(int c=1;c<=w;c++)
		{
			bool flag=true;
			int p=1;
			for(int i=c;i<=n;i+=w,p++)
			{
				if(s[i]!=t[p])
				{
					flag=false;
					break;
				}
			}
			p--;
			if(flag && p==m)
			{
				printf("Yes\n");
				return 0;
			}
		}
	printf("No\n");
	return 0;
}

C - Move It

贪心,在每个盒子里多出的物品中选最轻的拿走。

点击查看代码
#include<cstdio>
#include<vector>
#include<algorithm>
using namespace std;

const int N=1e5+5;
int n,a[N],w[N];
vector<int> box[N];

bool cmp(int x,int y){return w[x]<w[y];}
int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
		box[a[i]].push_back(i);
	}
	for(int i=1;i<=n;i++)
		scanf("%d",&w[i]);
	long long ans=0;
	for(int i=1;i<=n;i++)
	{
		sort(box[i].begin(),box[i].end(),cmp);
		for(int j=0;j<(int)box[i].size()-1;j++)
			ans+=w[box[i][j]];
	}
	printf("%lld\n",ans);
	return 0;
}

D - Ghost Ants

同向蚂蚁永远不互相穿过,所以只用考虑不同向的蚂蚁;又因为正向蚂蚁和逆向蚂蚁互相穿过只算一对,所以只用考虑每只正向蚂蚁会穿过多少逆向蚂蚁。

很明显,会和在 \(a_i\) 处的正向蚂蚁互相穿过的逆向蚂蚁的起始坐标应当在区间 \([a_i,a_i+2t]\) 内,所以将逆向蚂蚁排序以后二分(可以用 lower_bound 和 `upper_bound)找在这个区间内最左和最右的蚂蚁编号,其间蚂蚁的数量就可以累计到答案里。

点击查看代码
#include<cstdio>
#include<bitset>
#include<algorithm>
using namespace std;

const int N=2e5+5;
int n,aidx,bidx;
long long t,a[N],b[N];
char str[N];
bitset<N> type;

int main()
{
	scanf("%d%lld%s",&n,&t,str+1);
	for(int i=1;i<=n;i++)
		type[i]=str[i]-'0';
	for(int i=1;i<=n;i++)
	{
		long long x; scanf("%lld",&x);
		if(type[i]) a[++aidx]=x;
		else b[++bidx]=x;
	}
	sort(b+1,b+bidx+1);
	long long ans=0;
	for(int i=1;i<=aidx;i++)
	{
		int l=lower_bound(b+1,b+bidx+1,a[i])-b;
		int r=upper_bound(b+1,b+bidx+1,a[i]+(t<<1))-b-1;
		ans+=(r-l+1);
	}
	printf("%lld\n",ans);
	return 0;
}

E - Random Swaps of Balls

之前从来没有接触过这方面的题目(DP 概率),所以第一眼就放弃然后去做后面的题了。

算法是从这篇题解里学习的,这里就不多赘述了。

#include<cstdio>
#define LL long long
using namespace std;

const int K=1e5+5,P=998244353;
LL n,k,f[K];

LL quick_pow(LL x,LL y)
{
	LL res=1;
	while(y)
	{
		if(y&1) res=res*x%P;
		x=x*x%P;
		y>>=1;
	}
	return res;
}
LL inv(LL x){return quick_pow(x,P-2);}

int main()
{
	scanf("%lld%lld",&n,&k);
	LL leave=(((n-1)*inv(n*n%P))<<1)%P;
	LL back=(inv(n*n%P)<<1)%P;
	f[0]=1;
	for(int i=1;i<=k;i++)
	{
		f[i]=(1-leave)*f[i-1]+back*(1-f[i-1]);
		f[i]=(f[i]%P+P)%P;
	}
	LL ans = f[k] + (1-f[k])*inv(n-1)%P * (2+n)%P*(n-1)%P*inv(2)%P;
	printf("%lld\n",(ans%P+P)%P);
	return 0;
}

G - Suitable Edit for LIS

第一眼感觉很可做的样子,最后居然独立切出来了(虽然不是场切)。

不过我这个方法细节特别多,而且似乎是个假做法(对拍了 \(3000+\) 组数据后发现了 Hack 数据,不过这个做法也可以说 \(99.99\%\) 正确吧,至少题目数据没有能 Hack 掉我)。

简而言之就是在原本树状数组求 LIS 的基础上各种判断是否能新插入一个数进去,而且在序列长度相同情况下的选择优先级也需要很仔细。

因为不一定正确就不写解析了。

点击查看代码
#include<cstdio>
#include<algorithm>
#include<unordered_map>
using namespace std;

const int N=2e5+5;
int n,a[N],f[N];
bool added[N];

unordered_map<int,int> c;
inline int lowbit(int x){return x&-x;}
bool cmp_greater(int x,int y) //x>y
{
	if(f[x]!=f[y]) return f[x]>f[y];
	if(added[x]!=added[y]) return added[x]<added[y];
	if(a[x]!=a[y]) return a[x]<a[y]; //这一行和下一行可能交换与否都有可能出最优解
	if(x!=y) return x<y;
	return false;
}
int maxp(int x,int y)
{
	return cmp_greater(x,y)?x:y;
}
void update(int x,int y)
{
	for(x++;x<=1e9;x+=lowbit(x))
		c[x]=maxp(c[x],y);
	return;
}
int query(int x)
{
	int res=0;
	for(x++;x;x-=lowbit(x))
		res=maxp(res,c[x]);
	return res;
}

int main()
{
	scanf("%d",&n);
	for(int i=1;i<=n;i++)
		scanf("%d",&a[i]);
	int ans=0;
	a[0]=-0x3f3f3f3f;
	for(int i=1;i<=n;i++)
	{
		int pos=query(a[i]-1);
		if(pos!=i-1 && a[pos]!=a[i]-1 && !added[pos])
		{
			printf("added in %d\n",i);
			added[i]=true;
			f[i]=f[pos]+2;
			update(a[i],i);
		}
		else
		{
			added[i]=added[pos];
			f[i]=f[pos]+1;
			update(a[i],i);
		}
		printf("f[%d]=%d(from %d)\n",i,f[i],pos);
		if(i!=n && !added[i]) ans=max(ans,f[i]+1);
		else ans=max(ans,f[i]);
	}
	printf("%d\n",ans);
	return 0;
}
posted @ 2024-11-06 20:29  Jerrycyx  阅读(7)  评论(0编辑  收藏  举报