[ABC187] AtCoder Beginner Contest 187
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=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.