码迷,mamicode.com
首页 > 其他好文 > 详细

[ABC187]AtCoder Beginner Contest 187

时间:2021-01-06 11:50:46      阅读:0      评论:0      收藏:0      [点我收藏+]

标签:pac   removing   find   read   values   direct   code   a*   hand   

Tasks

Task Name Time Limit Memory Limit
A Large Digits 2 sec 1024 MB Submit
B Gentle Pairs 2 sec 1024 MB Submit
C 1-SAT 2 sec 1024 MB Submit
D Choose Me 2 sec 1024 MB Submit
E Through Path 2 sec 1024 MB Submit
F Close Group 3 sec 1024 MB Submit

A

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

int val(int n)
{
	int res=0;
	for(;n;n/=10) 
		res+=n%10;
	return res;
}

int main()
{
//	freopen("1.in","r",stdin);
	int a,b;
	cin>>a>>b;
	cout<<max(val(a),val(b))<<endl;
	return 0;
}

B

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<double,double> PDD;
typedef PDD Point;

#define x first
#define y second

int calc(Point a,Point b)
{
	double k=(a.y-b.y)/(a.x-b.x);
	if(k>=-1 && k<=1) return 1;
	else return 0;
}

const int N=1e3+5;

int n;
Point a[N];
int ans;

int main()
{
//	freopen("1.in","r",stdin);
	int i,j;
	
	scanf("%d",&n);
	for(i=1;i<=n;i++) 
		scanf("%lf%lf",&a[i].x,&a[i].y);
	
	for(i=1;i<=n;i++) 
		for(j=i+1;j<=n;j++) 
			ans+=calc(a[i],a[j]);
	
	cout<<ans<<endl;
	return 0;
}

讲的有内涵一点,此题是计算几何。

没卡精度好评。

C

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

int n;

set<string> mp0,mp1;

void read(string &s)
{
	static char a[20];
	scanf("%s",a);
	s=a;
}

int main()
{
//	freopen("1.in","r",stdin);
	int i;
	string s;
	
	scanf("%d",&n);
	for(i=1;i<=n;i++) {
		read(s);
//		cout<<s<<endl;
		if(s[0]==‘!‘) {
			s.erase(s.begin());
			if(mp0.count(s)) {
				printf("%s\n",s.c_str());
				return 0;
			}
			mp1.insert(s);
		}
		else {
			if(mp1.count(s)) {
				printf("%s\n",s.c_str());
				return 0;
			}
			mp0.insert(s);
		}
	}
	
	printf("satisfiable\n");
	return 0;
}

D

题意:

AtCoder City will hold a mayoral election. The candidates are Aoki and Takahashi.
The city consists of N towns, the i-th of which has Ai pro-Aoki voters and Bi pro-Takahashi voters. There are no other voters.
Takahashi can make a speech in each town.
If he makes a speech in some town, all voters in that town, pro-Takahashi or pro-Aoki, will vote for Takahashi.
On the other hand, if he does not make a speech in some town, the pro-Aoki voters in that town will vote for Aoki, and the pro-Takahashi voters will not vote.
To get more votes than Aoki, in how many towns does Takahashi need to make speeches at least?

简化题意:

给定 \(n\) 个点:

  • 若选第 \(i\) 个点, Takahashi 将会获得 \(a_i+b_i\) .
  • 若不选,pro-Aoki 将会获得 \(a_i\) .

选择尽量少的点,使 Takahashi 获得的更多。

思路 :

令 Takahashi 获得的为 \(sum_B\) , pro-Aoki 获得的为 \(sum_A\).

\[sum_B>sum_A \]

\[sum_B-sum_A>0 \]

\(sum=sumB-sumA\) ,考虑选和不选对 \(sum\) 的影响。

不妨初始都为不选,再一个个选。

所以 初始 \(sum=\sum_{i-1}^{n}-a_i\)

  • 若选第 \(i\) 个点, \(sum +=2a_i+b_i\)
  • 若不选, \(sum\) 不变。

选择尽量少的点使 \(sum>0\)

只需一直选 \(2a_i+b_i\) 最大的即可。

贪心

Code:

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

const int N=2e5+5;

struct town
{
	LL a,b;
	inline bool operator<(const town &t) const
	{
		return 2*a+b>t.a*2+t.b;
	}
}a[N];

int n;
LL sum;

int main()
{
//	freopen("1.in","r",stdin);
	int i;
	
	scanf("%d",&n);
	for(i=1;i<=n;i++) {
		scanf("%lld%lld",&a[i].a,&a[i].b);
		sum-=a[i].a;
	}
		
	sort(a+1,a+n+1);
	for(i=1;i<=n;i++) {
		sum+=2*a[i].a+a[i].b;
		if(sum>0) {
			printf("%d\n",);
			return 0;
		}
	}
	return 0;
}

E

dfs序+差分,裸题。

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

const int N=4e5+5;

int one[N],idx;
int Next[N],ver[N];
inline void AddEdge(int a,int b)
{
	Next[idx]=one[a],ver[idx]=b,one[a]=idx++;
	Next[idx]=one[b],ver[idx]=a,one[b]=idx++;
}

struct Edge
{
	int a,b;
}e[N];

int dfn[N],dfnt[N],times;
int dep[N];

void dfs(int x,int fa)
{
	dfn[x]=++times;
	dep[x]=dep[fa]+1;
	for(int i=one[x],y;~i;i=Next[i]) {
		y=ver[i];
		if(y==fa) continue;
		dfs(y,x);
	}
	dfnt[x]=times;
}

int n,m;
LL c[N];

int main()
{
//	freopen("1.in","r",stdin);
	int i;
	int opt,x,y,id;
	LL z;
	
	scanf("%d",&n);
	memset(one,-1,sizeof one);
	for(i=1;i<=n-1;i++) {
		scanf("%d%d",&e[i].a,&e[i].b);
		AddEdge(e[i].a,e[i].b);
	}
	
	dfs(1,0);
	
	scanf("%d",&m);
	while(m--) {
		scanf("%d%d%lld",&opt,&id,&z);
		if(opt==1) {
			x=e[id].a,y=e[id].b;
			if(dep[x]>dep[y]) {
				c[dfn[x]]+=z;
				c[dfnt[x]+1]-=z;
			}
			else {
				c[1]+=z;
				c[dfn[y]]-=z;
				c[dfnt[y]+1]+=z;
				c[n+1]-=z;
			}
		}
		
		else {
			x=e[id].a,y=e[id].b;
			if(dep[y]>dep[x]) {
				c[dfn[y]]+=z;
				c[dfnt[y]+1]-=z;
			}
			else {
				c[1]+=z;
				c[dfn[x]]-=z;
				c[dfnt[x]+1]+=z;
				c[n+1]-=z;
			}
		}
	}
	
	for(i=1;i<=n;i++) c[i]+=c[i-1];
	for(i=1;i<=n;i++)
		printf("%lld\n",c[dfn[i]]);
	return 0;
}

时间复杂度:\(O(n)\)

空间复杂度:\(O(n)\)

F

Problem Statement

Given is a simple undirected graph with N vertices and M edges. The vertices are numbered 1,2,…,N, and the i-th edge connects Vertices Ai and Bi.

Find the minimum possible number of connected components in the graph after removing zero or more edges so that the following condition will be satisfied:

Condition:
For every pair of vertices (a,b)such that 1≤a<b≤N, if Vertices a and b belong to the same connected component, there is an edge that directly connects Vertices a and b.

Constraints

  • All values in input are integers.
  • 1≤N≤18
  • 0≤M≤N(N?1)/2
  • 1≤Ai<Bi≤N
  • (Ai,Bi)≠(Aj,Bj) for i≠j.

题意:删边,保留尽量少的联通块,使 所有极大联通子图都为完全图。

一看 \(n \leq 18\) ,是状压没得跑了。

先遍历一遍,哪些子图可行,然后子集枚举即可。

#include<bits/stdc++.h>

using namespace std;
typedef long long LL;
typedef unsigned long long ULL;

const int N=19,S=(1<<19)+5;
int n,m;
bool w[N][N];
int f[S];

int main()
{
//	freopen("1.in","r",stdin);
	int i,j,k;
	int x,y;
	
	scanf("%d%d",&n,&m);
	for(i=1;i<=m;i++) {
		scanf("%d%d",&x,&y);
		x--,y--;
		w[x][y]=w[y][x]=true;
	}
	
	memset(f,0x3f,sizeof f);
	for(i=0;i<(1<<n);i++) {
		for(j=0;j<n;j++) {
			if(!((i>>j)&1)) continue;
			for(k=j+1;k<n;k++) {
				if(!((i>>k)&1)) continue;
				if(!w[j][k]) break;
			}
			if(k<n) break;
		}
		if(j==n) f[i]=1;
	}
	
	for(i=0;i<(1<<n);i++) 
		for(j=(i-1)&i;j;j=(j-1)&i) 
			f[i]=min(f[i],f[j]+f[i-j]);
	
	printf("%d\n",f[(1<<n)-1]);
	return 0;
}

时间复杂度:\(O(n^22^n+3^n)\) ,这 AtCoder 神机。

附:此题好像没法把一个一个点加入状态,因为如果要的话,还要维护状态内部的联通性信息,难以做到,所以只能一次把一个可行集合都加进来。

类似的题:

1118 分成互质组
524 愤怒的小鸟 (需优化)(可限定当前点的最小编号为更新后的最小编号 或 仅使用 bfs。

完结撒花

第二次 AK ABC.

[ABC187]AtCoder Beginner Contest 187

标签:pac   removing   find   read   values   direct   code   a*   hand   

原文地址:https://www.cnblogs.com/cjl-world/p/14224193.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!