Codeforces Gym 103409

本来写了一大半,电脑插头掉了/fn/fn/fn

是模拟赛,CCPC2021桂林站

D

对于 i,如果我要换到 j,找到右边第一个比 j 位置上数大的位置 k,交换 i,k 即可。

防止一次换完本来应该放中间的放不回去了。

查看代码
#include<bits/stdc++.h>
using namespace std;
int t,n,a[2025],b[2025],p[2025];
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n;
		for(int i=1;i<=n;++i)cin>>a[i],p[a[i]]=i;
		for(int i=1;i<=n;++i)cin>>b[i];
		queue<pair<int,int> >q;
		int cnt=0;
		for(int i=1;i<=n;++i){
//			cout<<"Test "<<i<<": \n";
//			for(int j=1;j<=n;++j)cout<<a[j]<<' ';
//			cout<<'\n';
//			for(int j=1;j<=n;++j)cout<<b[j]<<' ';
//			cout<<'\n';
			if(a[i]<b[i]){
				cnt=-1;
				break;
			}
			if(a[i]==b[i])continue;
			int x=i+1,y=p[b[i]]-1;
			int pos=0;
			vector<int>vec;
			vec.push_back(i);
			for(int j=x;j<=y;++j){
				if(a[j]>b[i]){
					vec.push_back(j);
				}
			}
			vec.push_back(p[b[i]]);
			for(int j=1;j<vec.size();++j){
				if(a[i]<a[vec[j]])continue;
				++cnt;
				q.push(make_pair(i,vec[j]));
				swap(p[a[i]],p[a[vec[j]]]);
				swap(a[i],a[vec[j]]);
			}
		}
		cout<<cnt<<'\n';
		if(cnt!=-1){
			while(!q.empty())cout<<q.front().first<<' '<<q.front().second<<'\n',q.pop();
		}
	} 
}

E

首先两次一定可以解决。第一次 u<v,第二次 u>v 即可,反正是有向图(

然后因为不能有环,所以出现环 2 次,没边 0 次,否则 1 次。

然后变成了找最小环问题。可以把点拉开变成出点和入点找找最短路 (为什么感觉像网络流 看能不能买下这个环就可以了!

查看代码
#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,m,c;
vector<pair<int,int> >nbr[4005];
void add(int u,int v,int w){
	nbr[u].push_back(make_pair(v,w));
	return;
}
struct node{
	int v,w;
	bool operator <(const node &nxt)const{
		return w>nxt.w;
	}
};
int in(int x){
	return x;
}
int out(int x){
	return x+n;
}
int dis[4005];
bool vis[4005];
int dijkstra(int s){
	priority_queue<node>pq;
	memset(vis,0,sizeof(vis));
	pq.push({s,0});
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	while(!pq.empty()){
		node cur=pq.top();
		pq.pop();
		if(vis[cur.v])continue;
		vis[cur.v]=1;
		for(auto to:nbr[cur.v]){
			if(dis[to.first]>dis[cur.v]+to.second){
				dis[to.first]=dis[cur.v]+to.second;
				pq.push({to.first,dis[to.first]});
			}
		}
	}
	return dis[s-n];
} 
int mini=1e9;
signed main(){
	ios::sync_with_stdio(0);
	cin>>n>>m>>c;
	for(int i=1;i<=m;++i){
		int u,v,w;
		cin>>u>>v>>w;
		add(out(u),in(v),w);
		mini=min(mini,w);
	}
	if(mini>c){
		cout<<0;
		return 0;
	}
	for(int i=1;i<=n;++i)add(in(i),out(i),0);
	mini=1e9;
	for(int i=1;i<=n;++i){
		mini=min(mini,dijkstra(out(i)));
	}
	if(mini>c){
		cout<<1;
		return 0;
	}
	else cout<<2;
	return 0;
}

K

爆搜+最短路分层图(

就是,你可以先跑最短路,然后按 dis 值分层!

然后,按这个分层搜索就可以了!

因为 n 只有 50

查看代码
#include<bits/stdc++.h>
using namespace std;
int n,m,w[2005];
struct edge{
	int v,c;
};
struct node{
	int v,w;
	bool operator<(const node &nxt)const{
		return w>nxt.w;
	}
};
vector<edge>nbr[55];
int dis[4005];
bool vis[4005];
void dijkstra(int s){
	priority_queue<node>pq;
	memset(vis,0,sizeof(vis));
	pq.push({s,0});
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	while(!pq.empty()){
		node cur=pq.top();
		pq.pop();
		if(vis[cur.v])continue;
		vis[cur.v]=1;
		for(auto to:nbr[cur.v]){
			if(dis[to.v]>dis[cur.v]+1){
				dis[to.v]=dis[cur.v]+1;
				pq.push({to.v,dis[to.v]});
			}
		}
	}
	return;
} 
int cnt[2005],ans[2005];//记录经过该公司的边的次数 
void dfs(int cur,int sum,int dist){
	if(dist==dis[cur])ans[cur]=min(ans[cur],sum);
	for(auto to:nbr[cur]){
		if(vis[to.v]||dis[to.v]!=dis[cur]+1)continue;
		vis[to.v]=1;
		cnt[to.c]++;
		dfs(to.v,sum+cnt[to.c]*w[to.c],dist+1);
		vis[to.v]=0;
		cnt[to.c]--;
	}
	return;
}
int main(){
	ios::sync_with_stdio(0);
	cin>>n>>m;
	for(int i=1;i<=m;++i)cin>>w[i];
	for(int i=1;i<=m;++i){
		int u,v,c;
		cin>>u>>v>>c;
		nbr[u].push_back({v,c});
		nbr[v].push_back({u,c});
	}
	dijkstra(1);
	memset(ans,0x3f,sizeof(ans));
	memset(vis,0,sizeof(vis));
	dfs(1,0,0);
//	for(int i=1;i<=n;++i)cout<<dis[i]<<'\n';
//	cout<<"split\n";
	for(int i=2;i<=n;++i)cout<<ans[i]<<'\n';
	return 0;
}

B

记三个数分别为 A,B,C

注意到 Ci=Ai+Bi+(Aj+Bj10)mod10, 其中 j 为最小的满足 j>iAj+Bj9 的位置 j

如果没有发生修改, 那么发生变化的位数为 0, 否则至少为 2

如果第 i 位从不进位变成进位或者从进位变成不进位, 那么高位会
发生变化直到最大的满足 j<iAj+Bj9 的位置 j
因此需要使用支持插入, 删除, 求前驱和后继的数据结构维护所
Ai+Bi9 的位置 i。 可以使用 std::set, 复杂度为 Θ((q+n)logn)

注意 corner case!

点击查看代码
#include<bits/stdc++.h>
using namespace std;
int n,q;
int a[3][1000005];
set<int>s;
int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin>>n>>q;
	for(int i=1;i<=n;++i){
		char c;
		cin>>c;
		a[1][i]=c-'0';
	}
	for(int i=1;i<=n;++i){
		char c;
		cin>>c;
		a[2][i]=c-'0';
		if(a[1][i]+a[2][i]!=9)s.insert(i);
	}
	while(q--){
		int r,c,d;
		cin>>r>>c>>d;
		if(a[r][c]==d){
			int pos;
			set<int>::iterator itt=s.upper_bound(c);
			if(itt==s.end())pos=n+1;
			else pos=*itt;
			cout<<(d+a[3-r][c]+(a[r][pos]+a[3-r][pos]>=10))%10<<' '<<0<<'\n';
			continue;
		}
		int past=a[r][c];
		if(a[r][c]+a[3-r][c]==9&&a[3-r][c]+d!=9)s.insert(c);
		if(a[r][c]+a[3-r][c]!=9&&d+a[3-r][c]==9)s.erase(c);
		a[r][c]=d;
		int pos;
		set<int>::iterator itt=s.upper_bound(c);
		if(itt==s.end())pos=n+1;
		else pos=*itt;
		int xx;
		set<int>::iterator it=s.lower_bound(c);
		if(it!=s.begin())it--,xx=*it;else xx=1;
		int x=(a[r][c]+a[3-r][c]+(a[r][pos]+a[3-r][pos]>=10))%10;
		int y;
		int q=(a[r][pos]+a[3-r][pos]>=10);
		if(past+a[3-r][c]+q>=10&&a[r][c]+a[3-r][c]+q<10||past+a[3-r][c]+q<10&&a[r][c]+a[3-r][c]+q>=10)y=c-xx+1;
		else y=1;
		cout<<x<<' '<<y+1<<'\n';
	}
}
posted @   Forever1507  阅读(42)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示