(Training 9)AtCoder Beginner Contest 187

A - Large Digits

给2个数 求出他们每一位的和比较大小并输出

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int main(){
	string a,b;
	cin>>a>>b;
	int ans1=0,ans2=0;
	for(int i=0;i<a.size();i++){
		ans1+=a[i]-'0';
	}
	for(int i=0;i<b.size();i++){
		ans2+=b[i]-'0';
	}
	printf("%d",max(ans1,ans2));
	return 0;
}

B - Gentle Pairs

给出n个坐标
求出能形成的直线斜率在-1到1之间的数量

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=1e5+10;
int x[N],y[N];
int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>x[i]>>y[i];
	}
	int ans=0;
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if(1.0*(y[i]-y[j])/(x[i]-x[j])<=1&&1.0*(y[i]-y[j])/(x[i]-x[j])>=-1)ans++;
		}
	}
	cout<<ans;
}

C - 1-SAT

题意:如果!+字符出现过2次是不安全的
入门不存在这样的 那么输出"satisfiable“

#include<iostream>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int N=2e5+10;
map<string,int>mp;
int main(){
	int n;
	scanf("%d",&n);
	string a;
	bool flag=0;
	string ans;
	for(int i=1;i<=n;i++){
		cin>>a;
		if(a[0]=='!'){
			if(mp.count(a.substr(1,a.size()-1))){
				flag=1;
				ans=a.substr(1,a.size()-1);
			}
			mp[a]=1;
		}
		else{
			if(mp.count("!"+a)){
				flag=1;
				ans=a;
			}
			mp[a]=1;
		}
	}
	if(flag){
		cout<<ans;
	}
	else cout<<"satisfiable";
}

D - Choose M

题意:高桥选择一个地方会得到a+b个支持者 另一个人得到所有的没被选的a
高桥不选择的话不会得到任何东西
问高桥最少选择多少个地方使得支持者大于另外一个人
思路:排序贪心即可

#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int N=5e5+10;
typedef long long LL;
LL a[N];
bool cmp(LL x,LL y){
	return x>y;
}
int main(){
	int n;
	scanf("%d",&n);
	LL sum=0;
	for(int i=1;i<=n;i++){
		int x,y;
		scanf("%d%d",&x,&y);
		sum-=x;
		a[i]=2*x+y;
	}
	sort(a+1,a+1+n,cmp);
	LL ans=0;
	for(int i=1;i<=n;i++){
		sum+=a[i];
		if(sum>0){
			printf("%d\n",i);
			return 0;
		}
	}
}

E - Through Path

思路:树形dp(树上差分) 首先我们以1为根节点 遍历所有节点
并将所有的确立自己的父亲
如果选择a b点中的a点
如果b是a的父亲 那么就是a的所有子树都要增加x 直接在ans[a]上增加
如果b不是a的父亲 那么说b是a的儿子 b上的所有子树都不能增加 而除了b和b的子树都要加 这里就是树上差分了 根节点+x (ans[1]+=x)而子树b全部要减去x(ans[b]-=x)
处理完所有询问后直接一边dfs 所有儿子的ans[u]加上ans[father]即可

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N=2e5+10;
struct Edge{
	int v,next;
}edge[N<<1];
int head[N],tot,p[N],a[N],b[N];
LL ans[N];
void add(int u,int v){
	edge[++tot]={v,head[u]};
	head[u]=tot;
}
void dfs(int u,int father){
	ans[u]+=ans[father];
	p[u]=father;
	for(int i=head[u];i;i=edge[i].next){
		int v=edge[i].v;
		
		if(v!=father){
			dfs(v,u);
		}
	}
}
int main(){
	int n,q;
	scanf("%d",&n);
	for(int i=1;i<n;i++){
		int u,v;
		scanf("%d%d",&a[i],&b[i]);
		add(a[i],b[i]);
		add(b[i],a[i]);
	}
	dfs(1,0);
	scanf("%d",&q);
	for(int i=1;i<=q;i++){
		int t,e,x,u,v;
		scanf("%d%d%d",&t,&e,&x);
		u=a[e],v=b[e];
		if(t==2){
			swap(u,v);
		}
		if(p[u]==v)ans[u]+=x;
		else ans[1]+=x,ans[v]-=x;
	}
	dfs(1,0);
	for(int i=1;i<=n;i++)
	printf("%lld\n",ans[i]);
}

F - Close Group

给出一个图差分成完全图
完全图数量最少是多少
点的数量只有18 这里我们思考二进制枚举 状态压缩dp
每一位表示选上这几个点 最少差分成几个完全图
check函数返回是否是完全图 如果是 返回1
最后枚举所有状态往后推 每个状态枚举自己的所有的差分子集取最小值

#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=20;
int f[1<<N];
int G[N][N],n,m;
int check(int x){
	for(int i=1;i<=n;i++){
		for(int j=i+1;j<=n;j++){
			if((x>>(i-1))&1){
					if((x>>(j-1))&1){
						if(!G[i][j])return n;
					}
				}
		}
	}
	return 1;
}
int main(){
	scanf("%d%d",&n,&m);
	for(int i=1;i<=m;i++){
		int u,v;
		scanf("%d%d",&u,&v);
		G[u][v]=G[v][u]=1;
	}
	
	for(int i=1;i<(1<<n);i++){
		f[i]=check(i);
	}
	
	for(int i=1;i<(1<<n);i++){
		for(int s=i;s;s=i&(s-1)){
			f[i]=min(f[i],f[i^s]+f[s]);
		}
	}
	cout<<f[(1<<n)-1];
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值