Atcoder Beginner Contest 417 A-E

平时只有写了A-E才来发题解的,然后发现自己很久没有发ABC的题解了(TT)
image
为了庆祝我的rating起死回生,来水题解了。

不过感觉ABC最近好像变难了

AB

#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=x*10+c-48;
	x=(f ? -x : x);
	return;
}
int n,l,r;
int main(){
	read(n),read(l),read(r);
	string s;
	cin>>s;
	for(int i=l;i<=n-r-1;i++) cout<<s[i];
	return 0;
}
//^o^
#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e6+5;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=x*10+c-48;
	x=(f ? -x : x);
	return;
}
multiset<int> st;
int n,m;
int main(){
	read(n),read(m);
	for(int i=1;i<=n;i++){
		int in;
		read(in);
		st.insert(in);
	}
	for(int i=1;i<=m;i++){
		int in;
		read(in);
		if(st.find(in)!=st.end()) st.erase(st.find(in));
	}
	for(auto i=st.begin();i!=st.end();i++){
		cout<<*i<<' ';
	}
	return 0;
}
//^o^

用STL提供的multiset搞就可以了

C

等式变形
j-i=a[i]+a[j] -> j-a[j]=a[i]+i

然后建个桶就可以做啦

#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=2e5+5;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=x*10+c-48;
	x=(f ? -x : x);
	return;
}
int a[maxn];
int t[maxn<<1];
int n;
int main(){
	read(n);
	for(int i=1;i<=n;i++) read(a[i]);
	LL ans=0;
	for(int i=n;i>=1;i--){
		ans+=t[a[i]+i];
		if(i-a[i]>0) ++t[i-a[i]];
	}
	cout<<ans<<endl;
	return 0;
}
//^o^

D

(已补)

赛时想的是记录当开始时初始值在不同区间时所对的答案

对于每一次收到礼物,会产生三个区间

1.p[i]>=now 对于区间0p[i]增加一个a[i]
2.p[i]<now&&now>=b[i] 对于区间max(p[i]+1,b[i])inf减去一个b[i]
3.p[i]<now&&now<b[i] 对于区间p[i]+1b[i]-1设为0

但是这么做会让程序十分复杂赛时没有调出来,而且对于初始值极大的问题就束手无策了

考虑动态规划,注意数据范围,所有涉及心情变化的值均小于等于500

那么可以说明,当一个1000以内的心情加入运算时,这个值一定会持续保留在1000以内

设计dp[i][j]表示第i次运算前,当前心情为j,最后会达到的心情

对于初始值极大的问题,保留dp的第一维(也就是第i次运算时),二分需要减去多少才会达到1000以内

然后在dp的当前次运算中取答案即可,时间复杂度为O(mn + q log n)

#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1e4+5;
const int maxm=1005;
const int m=1000;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=x*10+c-48;
	x=(f ? -x : x);
	return;
}
int p[maxn],a[maxn],b[maxn];
int dp[maxn][m];
int sum[maxn];
int n,q;
int main(){
	read(n);
	for(int i=1;i<=n;i++){
		read(p[i]),read(a[i]),read(b[i]);
		sum[i]=sum[i-1]+b[i];
	}
	for(int i=0;i<=m;i++) dp[n+1][i]=i;
	for(int i=n;i>=1;i--){
		for(int j=0;j<=m;j++){
			if(p[i]>=j) dp[i][j]=dp[i+1][j+a[i]];
			else dp[i][j]=dp[i+1][max(j-b[i],0)];
		}
	}
	read(q);
	int in;
	while(q--){
		read(in);
		int i=lower_bound(sum,sum+n+1,in-m)-sum;
		//cout<<i<<" ans=";
		if(i==n+1) printf("%d\n",in-sum[n]);
		else printf("%d\n",dp[i+1][in-sum[i]]);
	}
	return 0;
}
//^o^

E

dfs模板,给每个点的边排个序就好,不用回溯

#include<bits/stdc++.h>
#define usetime() (double)clock () / CLOCKS_PER_SEC * 1000.0
using namespace std;
typedef long long LL;
const int maxn=1005;
void read(int& x){
	char c;
	bool f=0;
	while((c=getchar())<48) f|=(c==45);
	x=c-48;
	while((c=getchar())>47) x=x*10+c-48;
	x=(f ? -x : x);
	return;
}
int t;
vector<int> mp[maxn];
vector<int> ans;
bool vis[maxn];
int n,m,x,y;
bool dfs(int u){
	if(u==y){
		ans.push_back(u);
		return 1;
	}
	for(int i=0;i<mp[u].size();i++){
		int v=mp[u][i];
		if(vis[v]) continue;
		vis[v]=1;
		if(dfs(v)){
			ans.push_back(u);
			return 1;
		}
	}
	return 0;
}
int main(){
	read(t);
	while(t--){
		read(n),read(m),read(x),read(y);
		int u,v;
		ans.resize(0);
		for(int i=1;i<=n;i++){
			mp[i].resize(0);
			vis[i]=0;
		}
		for(int i=1;i<=m;i++){
			read(u),read(v);
			mp[u].push_back(v);
			mp[v].push_back(u);
		}
		for(int i=1;i<=n;i++){
			sort(mp[i].begin(),mp[i].end());
		}
		vis[x]=1;
		dfs(x);
		for(int i=ans.size()-1;i>=0;i--){
			printf("%d ",ans[i]);
		}
		printf("\n");
	}
	return 0;
}
//^o^

/*

最近刚从HL中学集训回来,本来还打算写游记的,结果照片忘记拍了TT

回来ABC似乎长进不大,但能重新拾起对OI的热爱,认识到自己的不足,那就是好事吧

八月份还有一次HL集训,这次一定带回照片 ( ̄▽ ̄)

*/

posted @ 2025-08-02 23:01  huangems  阅读(87)  评论(0)    收藏  举报