2022团队程序设计天梯赛

L2-041 插松枝

在这里插入图片描述
模拟
不能多空格
每次插松枝的时候先判断盒子(栈)后判断推送器(数组)

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
int n,m,k;
void slove(){
	cin>>n>>m>>k;
	int cnt=0,lxt=105;
	stack<int>s;
	vector<int>a(n);
	vector<vector<int>>ans;
	vector<int>t;
	for(auto &x:a)cin>>x;
	for(int i=0;i<n;i++){
		int x=a[i];
		while(s.size()&&s.top()<=lxt){
			m++;
			cnt++;
			t.push_back(s.top());
			lxt=s.top();
			s.pop();
			if(cnt==k){
				ans.push_back(t);
				lxt=105;
				cnt=0;
				t.clear();
			}
		}
		if(lxt>=x&&cnt<k){
			cnt++;
			t.push_back(x);
			lxt=x;
			if(cnt==k){
				ans.push_back(t);
				lxt=105;
				t.clear();
				cnt=0;
			}
		}
		else {
			if(m)m--,s.push(x);
			else {
				i--;
				ans.push_back(t);
				cnt=0;
				lxt=105;
				t.clear();
			}
		}
	}
	while(s.size()){
		if(s.top()<=lxt){
			cnt++;
			t.push_back(s.top());
			lxt=s.top();
		}
		else {
			ans.push_back(t);
			t.clear();
			cnt=1;
			lxt=s.top();
			t.push_back(s.top());
		}
		if(cnt==k){
			ans.push_back(t);
			lxt=105;
			t.clear();
			cnt=0;
		}
		s.pop();
	}
	if(t.size())ans.push_back(t);
	int p=0;
	for(auto tt:ans){
		if(p)cout<<endl;
		p=1;
		int q=0;
		for(auto x:tt){
			if(q)cout<<" ";
			q=1;
			cout<<x;
		}
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}

L2-042 老板的作息表

在这里插入图片描述

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
struct node{
	int h1,h2,m1,m2,s1,s2;
};
bool cmp(node a,node b){
	if(a.h1==b.h1&&a.m1==b.m1)return a.s1<b.s1;
	if(a.h1==b.h1)return a.m1<b.m1;
	return a.h1<b.h1;
}
void slove(){
	int n;
	cin>>n;
	vector<node>a(n);
	for(int i=0;i<n;i++){
		scanf("%d:%d:%d - %d:%d:%d",&a[i].h1,&a[i].m1,&a[i].s1,&a[i].h2,&a[i].m2,&a[i].s2);		
	}
	node ed;
	ed.h1=ed.h2=23;
	ed.m1=ed.m2=59;
	ed.s1=ed.s2=59;
	a.push_back(ed);
	int h=0,m=0,s=0;
	sort(a.begin(),a.end(),cmp);
	for(auto now:a){
		if(h!=now.h1||m!=now.m1||s!=now.s1){
			printf("%02d:%02d:%02d - %02d:%02d:%02d\n",h,m,s,now.h1,now.m1,now.s1);
		}
		h=now.h2,m=now.m2,s=now.s2;
	}
}
int main(){
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}

L2-043 龙龙送外卖

在这里插入图片描述
每出现一个外卖点则往上跑到第一个曾经去过的外卖点或外卖站(根节点),所跑总路程+=该路程*2(可能要来回),并记录新路径加入后最长的一条路径,每次答案即为 所跑总路程-最长路径 (少跑一个最长的回)。

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
#define int long long
int n,m;
int fa[100005],s[100005],rot,mx,sum;
int dfs(int x,int l){
	if(x==rot||s[x]){
		mx=max(mx,s[x]+l);
		return l*2;
	}
	int res=dfs(fa[x],l+1);
	s[x]=s[fa[x]]+1;
	return res;
}
void slove(){
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>fa[i];
		if(fa[i]==-1)rot=i;
	}
	while(m--){
		int x;
		cin>>x;
		sum+=dfs(x,0);
		cout<<sum-mx<<endl;
	}
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}

L2-044 大众情人

在这里插入图片描述
floyd板子

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
#define int long long
int n;
int d[505][505],mx[505];
bool sx[505];
void slove(){
	cin>>n;
	memset(d,127,sizeof d);
	int inf=d[0][0];
	for(int i=1;i<=n;i++){
		char ch;
		cin>>ch;
		int m;
		cin>>m;
		if(ch=='F')sx[i]=true;
		while(m--){
			int x,y;
			scanf("%lld:%lld",&x,&y);
			d[i][x]=y;
		}
	}
	for(int k=1;k<=n;k++){
		for(int i=1;i<=n;i++){
			for(int j=1;j<=n;j++){
				if(i==j||d[i][k]==inf||d[k][j]==inf)continue;
				d[i][j]=min(d[i][j],d[i][k]+d[k][j]);
			}
		}
	}
	int fmn=inf,mmn=inf;
	for(int i=1;i<=n;i++){
		for(int j=1;j<=n;j++){
			if(sx[i]==sx[j])continue;
			mx[i]=max(mx[i],d[j][i]);
		}
		if(sx[i])fmn=min(fmn,mx[i]);
		else mmn=min(mmn,mx[i]);
	}
	vector<int>ff,mm;
	for(int i=1;i<=n;i++){
		if(sx[i]&&mx[i]==fmn)ff.push_back(i);
		if(!sx[i]&&mx[i]==mmn)mm.push_back(i);
	}
	int p=0;
	sort(ff.begin(),ff.end());
	sort(mm.begin(),mm.end());
	for(auto x:ff){
		if(p)cout<<" ";
		p=1;
		cout<<x;
	}
	cout<<endl;
	p=0;
	for(auto x:mm){
		if(p)cout<<" ";
		p=1;
		cout<<x;
	}
}
signed main(){
//	ios::sync_with_stdio(false);
//	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}

L3-032 千手观音

在这里插入图片描述
可以通过输入给出的大小关系建边后跑bfs得到其拓扑序,为了使得无法确定相对顺序的符号可以使用优先队列从小到达排序满足字典序升序

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
map<string,int>mp;
int tot;
string st[10005];
vector<int>to[10005];
int in[10005];
void slove(){
	int n;
	cin>>n;
	vector<string>pre;
	for(int i=1;i<=n;i++){
		string s;
		cin>>s;
		vector<string>now;
		int cnt=0;
		string t="";
		for(int j=0;j<s.length();j++){
			if(s[j]=='.'||j+1==s.length()){
				if(j+1==s.length())t+=s[j];
				if(!mp.count(t))mp[t]=++tot,st[tot]=t;
				now.push_back(t);
				t="";
			}
			else t+=s[j];
		}
		if(i==1)pre=now;
		else{
			if(pre.size()==now.size()){
				for(int i=0;i<pre.size();i++){
					if(pre[i]==now[i])continue;
					to[mp[pre[i]]].push_back(mp[now[i]]);
					in[mp[now[i]]]++;
					break;
				}
			}
			pre=now;
		}
	}
	priority_queue<string,vector<string>,greater<string> >q;
	for(int i=1;i<=tot;i++){
		if(in[i]==0)q.push(st[i]);
	}
	vector<string>ans;
	while(q.size()){
		string t=q.top();q.pop();
		int x=mp[t];
		ans.push_back(t);
		for(auto y:to[x]){
			in[y]--;
			if(in[y]==0){
				q.push(st[y]);
			}
		}
	}
	bool p=false;
	for(auto x:ans){
		if(p)cout<<".";
		p=true;
		cout<<x;
	}
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}

L3-032 关于深度优先搜索和逆序对的题应该不会很难吧这件事在这里插入图片描述

首先我们先思考

不可调换相对位置的点 :

若点x和点y之间的关系是 x为y的祖先或y为x的祖先 则他们之间的相对位置不会变化。可以使用树状数组在dfs中存储到目前点的祖先已经有哪些点了,来得出逆序对个数。

可以调换相对位置的点:

若点x和点y之间不为 祖先或孩子,那他们的遍历顺序会影响他们的相对位置。假设 x<y 并且还有若干个可以调换顺序的点,在这些点的全排列中有 1/2 的情况 x在y前面,另外 1/2 的情况 y在x前面(逆序)。
对于每个有son个子节点的点的遍历顺序的所造成的可能的全排列的个数为 son!
对于整棵树而言则是每个节点的全排列个数的乘积 记为 bl
对于每个点x而言 所有不为其祖先和孩子的点都是可以调换相对位置的点y,其贡献为 bl/2*(y的个数)/2 在计算y的贡献时也会有x所以需要乘 1/2
在所有的排列中 ‘不可调换相对位置的点’ 的贡献都是不会变的所以需要乘上 bl

#pragma GCC optimize(1)
#pragma GCC optimize(2)
#pragma GCC optimize(3)
#include<bits/stdc++.h>
using namespace std;
#define endl "\n"
typedef long long ll;
#define int long long 
#define lowbit(x) (x&-x)
const int mod=1e9+7;
int n,rt;
vector<int>to[300005];
int ans,sz[300005],dep[300005],tr[300005],bl=1;
int qmi(int a, int k, int p)  // 求a^k mod p
{
	int res = 1 % p;
	while (k)
	{
		if (k & 1) res = (ll)res * a % p;
		a = (ll)a * a % p;
		k >>= 1;
	}
	return res;
}//逆元qmi(n!,p-2,p)
void add(int x,int k){
	while(x<=n){
		tr[x]+=k;
		x+=lowbit(x);
	}
}
int ask(int x){
	int res=0;
	while(x){
		res+=tr[x];
		x-=lowbit(x);
	}
	return res;
}
void dfs(int x,int fa){
	sz[x]=1;
	dep[x]=dep[fa]+1;
	int t=ask(n-x+1),son=0,tt=1;
	ans=(ans+t)%mod;
	add(n-x+1,1);
	for(auto y:to[x]){
		if(y==fa)continue;
		tt=(tt*(++son))%mod;
		dfs(y,x);
		sz[x]+=sz[y];
	}
	if(tt>1)bl=bl*tt%mod;
	add(n-x+1,-1);
}
void slove(){
	cin>>n>>rt;
	for(int i=1;i<n;i++){
		int x,y;
		cin>>x>>y;
		to[x].emplace_back(y);
		to[y].emplace_back(x);
	}
	int e=qmi(2,mod-2,mod);
	dfs(rt,0);
	ans=ans*bl%mod;
	for(int i=1;i<=n;i++){
		int res=n-dep[i]-sz[i]+1;
		ans=(ans+bl*res%mod*e%mod*e%mod)%mod;
	}
	cout<<ans<<endl;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0);cout.tie(0);
	int T=1;
//	cin>>T;
	while(T--){
		slove();
	}
	return 0;
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值