Codeforces Div3 #547

C-Polycarp Restores Permutation

简单题。给出了一个数组的差分然后询问是否可能是个全排列的差分,如果可能的话就构造一个全排列出来。我们只要任意设定首项就能得到一个新的数组,我们使得这个新的数组里面最小的那个数字变成1,然后调整这个数组。最后再判断一下是不是全排列就好了。注意这个数字可能很大。所以判定的时候最好用set或者写个条件。cf里面的第一发fst送给了这道题。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2e5+50;
ll p[N];
int vis[N];
int main() {
	p[1]=0;
	int n;
	scanf("%d",&n);
	for(int i=2;i<=n;i++) {
		ll x; 
		scanf("%lld",&x);
		p[i]=p[i-1]+x;
	}
	ll mi=1e18;
	for(int i=1;i<=n;i++) mi=min(mi,p[i]);
	ll add=1-mi;
	for(int i=1;i<=n;i++) p[i]+=add;
	for(int i=1;i<=n;i++) {
		if(p[i]>=1&&p[i]<=n) vis[p[i]]++;
	}
	for(int i=1;i<=n;i++) {
		if(vis[i]!=1) return 0*printf("-1\n");
	}
	for(int i=1;i<=n;i++) printf("%lld ",p[i]);
	return 0;
}

D-Colored Boots

模拟题。这道题是说给定两个串,让你求出最多的匹配数。当然这里面有一些是问号,问号是可以和任意的字符匹配的。存下来第一个串里面每个字符的下标。用第二个串去匹配它,先尽量考虑字符和字符的匹配。如果这个字符已经确定无法匹配到第一个串的字符再去和第一个串的问号匹配,最后再处理掉第二个字符串的所有的问号。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=150050;
char s1[N],s2[N];
vector<int> v[256],sp; 
vector<pair<int,int> > ans;
int add(int x,int y) {
	if(!v[x].size()) return 0;
	ans.push_back(make_pair(v[x][v[x].size()-1],y));
	v[x].pop_back();
	return 1;
}
int main() {
	int n;
	scanf("%d",&n);
	scanf("%s%s",s1+1,s2+1);
	for(int i=1;i<=n;i++) v[s1[i]].push_back(i);
	for(int i=1;i<=n;i++) {
		if(s2[i]=='?') sp.push_back(i);
		else if(!add(s2[i],i)) {
			add('?',i);
		}
	}
	for(auto &i:sp) {
		for(int j=0;j<=256;j++)
			if(add(j,i)) 
				break;
	}
	printf("%d\n",ans.size());
	for(auto &x:ans)  {
		printf("%d %d\n",x.first,x.second);
	}
	
	return 0;
}

E-Superhero Battle

模拟题。首先显然怪兽只有一种情况是不会死的。那就是在第一轮没死并且第一轮的生命增量的总和是非负的。否则怪兽一定会死。要么第一轮的时候就已经死了,这个只需要去判断一下就可以了。要么就是经过几个整的Round然后在最后一个Round某个地方死掉。直接枚举每一个位置,然后计算出怪兽在这个位置死掉之前就要消耗掉多少的血量。然后除掉每一轮掉的血量就好了。这个算法的正确性显然就是我既然这个时刻才会死,那么如果我枚举的是前面的位置,一定还要多加若干轮才能让我生命值为负计算出来的时间必定是大于我枚举的现在的这个位置。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2e5+50;
ll H,h[N],mi=1e18;
int main() {
	int n;
	ll res=1e18;
	bool die=false;
	scanf("%lld%d",&H,&n);
	for(int i=1;i<=n;i++) scanf("%lld",&h[i]);
	for(int i=1;i<=n;i++) { h[i]+=h[i-1];}
	for(int i=1;i<=n;i++) {
		if(h[i]<=-H) {
			return 0*printf("%d\n",i);
		}
	}
	if(h[n]<0) die=true;
	if(!die) return 0*printf("-1\n");
	for(int i=1;i<=n;i++) {
		if(h[i]>=0) continue;
		ll Hp=H+h[i];
		ll ans=0;
		if(Hp%(-h[n])==0) ans=Hp/(-h[n])*n;
		else ans=((Hp/(-h[n]))+1)*n;
		res=min(res,ans+i);
	}
	printf("%lld\n",res);
	return 0;
}

F2-Same Sum Blocks (Hard)

Easy和Hard并没有任何本质的区别。要求出最多的不交区间,并且每个区间和都是相同的。首先计算出前缀,然后对于每一个区间和都保存下来它们的区间,然后对于每个特定区间和贪心找最多线段。也就是按照右端点排序贪心。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2000;
int a[N];
map<int,vector<pair<int,int> > >mp;
int main() {
	int n;
	scanf("%d",&n);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]);
	for(int r=1;r<=n;r++) {
		int sum=0;
		for(int l=r;l>=1;l--) {
			sum+=a[l];
			mp[sum].push_back(make_pair(r,l)); 
		}
	}
	int res=0;
	vector<pair<int,int> >best;
	for(auto &it:mp) {
		vector<pair<int,int> > &p=it.S;
		vector<pair<int,int> > now;
		int r=-1;
		int sum=0;
		for(auto Seg:p) {
			if(Seg.S>r) {
				sum++;
				r=Seg.F;
				now.push_back(make_pair(Seg.S,Seg.F));
			}
		}
		if(sum>res) {
			res=sum;
			best=now;
		}
	}
	printf("%d\n",res);
	for(auto &it:best) {
		printf("%d %d\n",it.F,it.S);
	}
		
	return 0;
}

G-Privatization of Roads in Treeland

题意可以转化为给一个无向树的树边染色,然后这里面出边有相同颜色的结点的个数不能超过k个。求最少的染色数。很容易证明我们只要把结点的度数按照大小排序并统计。然后从大往下找找到多少个点的数量是大于k个。染色数就是当前这个点的度数。这也是贪心思想,最大程度利用了k个点可以允许被染相同的颜色。因为是树,从上往下,两个只会共用一条树边。所以只要保证每个点由上往下以及连接每个子树的边的颜色不同就好了。由顶向下dfs一遍构造出来就好了。

#pragma GCC optimize(3,"Ofast","inline")
#include<bits/stdc++.h>
#define pb push_back
#define F first
#define S second
using namespace std;
typedef long long ll;
const int inf=0x3f3f3f3f;
const ll INF=LONG_LONG_MAX;
const int N=2e5+50;
vector<pair<int,int> >G[N];
int D[N],cnt[N],col[N],Mod;
void dfs(int u,int fa,int color) {
	for(auto edge:G[u]) {
		int v=edge.F;
		if(v==fa) continue;
		int id=edge.S;	
		col[id]=color%Mod;
		color++;
		dfs(v,u,color%Mod);
	}
}
int main() {
	int n,k;
	scanf("%d%d",&n,&k);
	for(int i=1;i<n;i++) {
		int u,v;
		scanf("%d%d",&u,&v);
		G[u].push_back({v,i});
		G[v].push_back({u,i});
		++D[u],++D[v];
	} 
	for(int i=1;i<=n;i++) cnt[D[i]]++;
	for(int i=n-1;i>=1;i--) cnt[i]+=cnt[i+1];
	for(int i=n-1;i>=1;i--)  {
		if(cnt[i]>k) { Mod=i;break;	}
	}
	dfs(1,0,0);
	printf("%d\n",Mod);
	for(int i=1;i<n;i++)
		printf("%d ",col[i]+1);
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值