Helvetic Coding Contest 2019
Posted fengxunling
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Helvetic Coding Contest 2019相关的知识,希望对你有一定的参考价值。
题目链接:戳我
小注:其中部分(大括号不换行的)代码是BLUESKY007神仙写的。
小注2:如果可以的话,B2,C2,E3明天更。
CF1184 A1
直接枚举,以根号的时间复杂度判断即可。注意x,y都是正整数。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
#define ll long long
using namespace std;
ll r;
inline ll calc(ll x)
ll cur=r-x*x-x-1;
if(cur<=0) return -1;
if(cur%(2*x)==0) return cur/(2*x);
else return -1;
int main()
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%lld",&r);
for(ll i=1;i<=1000000;i++)
if(calc(i)>0)
printf("%lld %lld\n",i,calc(i));
return 0;
printf("NO\n");
return 0;
CF1184 A2
我们可以知道对于k,如果\(gcd(k,n)\)可以的话,那么k一定也可以。
所以我们就把枚举k才能计算的东西降低到了log的时间复杂度。
然后按每次长度为k在环上往后跳,直到跳到一个点第二次。在这期间,显然其中为1的边的个数为偶数才是可行方案。
那么直接把它们异或起来就行了。QAQ
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 200010
using namespace std;
int n,ans;
int cnt[MAXN],done[MAXN];
char s[MAXN];
int main()
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
scanf("%s",s);
for(int i=1;i<=n;i++) cnt[__gcd(i,n)]++;
for(int i=1;i<=n;i++)
if(cnt[i])
bool flag=false;
memset(done,0,sizeof(done));
for(int j=0;j<n;j++)
if(!done[j])
int cur_ans=0,x=j;
while(!done[x])
cur_ans^=(s[x]-'0');
done[x]=1;
x=(x+i)%n;
if(cur_ans) flag=true;
if(!flag) ans+=cnt[i];
printf("%d\n",ans);
return 0;
CF1184 B1
二分。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
struct base
int d,g,id;
bool operator<(const base&rhs)const
return d!=rhs.d?d<rhs.d:id<rhs.id;
ba[N];
int s,b,a[N];
long long sum[N];
int bs(int l,int r,int u)
if(l==r)
return l;
int mid=(l+r+1)>>1;
if(ba[mid].d<=u)
return bs(mid,r,u);
else
return bs(l,mid-1,u);
int main()
scanf("%d%d",&s,&b);
for(int i=1;i<=s;i++)
scanf("%d",&a[i]);
for(int i=1;i<=b;i++)
scanf("%d%d",&ba[i].d,&ba[i].g);
ba[i].id=i;
sort(ba+1,ba+b+1);
for(int i=1;i<=b;i++)
sum[i]=sum[i-1]+ba[i].g;
for(int i=1;i<=s;i++)
printf("%lld%c",sum[bs(0,b,a[i])]," \n"[i==s]);
return 0;
CF1184 B2
CF1184 C1
暴力地找四个点,然后判断一下他们构成的矩形上是不是正好缺少一个点qwq
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
using namespace std;
int n;
struct Nodeint x,y;node[MAXN];
inline void calc(int a,int b,int c,int d)
int down=0x3f3f3f3f,up=0,ll=0x3f3f3f3f,rr=0,cnt=0;
ll=min(ll,node[a].x),ll=min(ll,node[b].x),ll=min(ll,node[c].x),ll=min(ll,node[d].x);
rr=max(rr,node[a].x),rr=max(rr,node[b].x),rr=max(rr,node[c].x),rr=max(rr,node[d].x);
down=min(down,node[a].y),down=min(down,node[b].y),down=min(down,node[c].y),down=min(down,node[d].y);
up=max(up,node[a].y),up=max(up,node[b].y),up=max(up,node[c].y),up=max(up,node[d].y);
int kkk;
for(int i=1;i<=n;i++)
if(ll<=node[i].x&&node[i].x<=rr&&(node[i].y==down||node[i].y==up)) cnt++;
else if(down<=node[i].y&&node[i].y<=up&&(node[i].x==ll||node[i].x==rr)) cnt++;
else kkk=i;
if(cnt==n-1)
printf("%d %d\n",node[kkk].x,node[kkk].y);
exit(0);
int main()
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d",&n);
for(int i=1;i<=4*n+1;i++)
scanf("%d%d",&node[i].x,&node[i].y);
n=4*n+1;
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
for(int k=j+1;k<=n;k++)
for(int p=k+1;p<=n;p++)
calc(i,j,k,p);
return 0;
CF1184 C2
CF1184 D1
开始还以为要用链表直接模拟即可,注意判断一下加入和删除的位置和当前主人公所在位置的大小。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define MAXN 100010
#define ll long long
using namespace std;
int n,m,k,t;
int main()
#ifndef ONLINE_JUDGE
freopen("ce.in","r",stdin);
#endif
scanf("%d%d%d%d",&n,&k,&m,&t);
while(t--)
int op,pos;
scanf("%d%d",&op,&pos);
if(op==0)
if(pos>=k) n=pos;
else n-=pos,k-=pos;
else
if(pos<=k) k++,n++;
else n++;
printf("%d %d\n",n,k);
return 0;
CF1184 E1
二分一下桥1的值,看看能否在最小生成树中。
#include<bits/stdc++.h>
using namespace std;
const int N=1e6+6;
int n,m,fr[N],to[N],w[N],fa[N],siz[N];
bool usd[N];
int find(int u)
return fa[u]==u?fa[u]:fa[u]=find(fa[u]);
struct edge
int u,v,w,id;
bool operator<(const edge&rhs)const
return w<rhs.w;
e[N];
bool unifa(int u,int v)
if(find(u)==find(v))
return 0;
fa[find(v)]=find(u);
return 1;
bool can(int u)
for(int i=1;i<=n;i++)
fa[i]=i;
for(int i=2;i<=m;i++)
if(e[i].w<u)
unifa(e[i].u,e[i].v);
return unifa(e[1].u,e[1].v);
int bs(int l,int r)
if(l==r)
return l;
int mid=(l+r+1)>>1;
if(!can(mid))
return bs(l,mid-1);
else
return bs(mid,r);
int main()
scanf("%d%d",&n,&m);
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].u,&e[i].v,&e[i].w);
e[i].id=i;
printf("%d\n",bs(0,1e9));
return 0;
CF1184 E2
我们先构建最小生成树,然后每次处理到一条不在最小生成树上的边的时候,倍增往上面找最小的一条边的值就行了。
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
#define debug printf("%d %s\n",__LINE__,__FUNCTION__)
using namespace std;
const int N=1e6+6;
int n,m,fa[N],dep[N];
vector<int>G[N],W[N];
bool vis[N];int ans[N];
int find(int u)
return fa[u]==u?fa[u]:fa[u]=find(fa[u]);
bool unifa(int u,int v)
if(find(u)==find(v))
return 0;
fa[find(v)]=find(u);
return 1;
struct edge
int u,v,w,id;
edge(int ru=0,int rv=0,int rw=0,int ri=0)
u=ru;v=rv;w=rw;id=ri;
bool operator<(const edge&rhs)const
return w<rhs.w;
e[N];
void addedge(int u,int v,int w)
G[u].push_back(v);W[u].push_back(w);
int jump[N][18],mx[N][18];
void dfs(int u,int fr)
for(int i=0,v;i<(int)G[u].size();i++)
v=G[u][i];
if(v==fr)
continue;
dep[v]=dep[u]+1;
jump[v][0]=u;
mx[v][0]=W[u][i];
for(int j=1;j<18;j++)
jump[v][j]=jump[jump[v][j-1]][j-1];
mx[v][j]=max(mx[v][j-1],mx[jump[v][j-1]][j-1]);
dfs(v,u);
pii lca(int u,int v)
int rep=0;
if(dep[u]<dep[v])
swap(u,v);
for(int i=17;~i;i--)
if(dep[jump[u][i]]>=dep[v])
rep=max(mx[u][i],rep);
u=jump[u][i];
if(u==v)
return mk(u,rep);
for(int i=17;~i;i--)
if(jump[u][i]!=jump[v][i])
rep=max(rep,max(mx[u][i],mx[v][i]));
u=jump[u][i];
v=jump[v][i];
rep=max(rep,max(mx[u][0],mx[v][0]));
return mk(jump[u][0],rep);
int query(int u,int v)
return lca(u,v).se;
int main()
scanf("%d%d",&n,&m);
for(int i=1,u,v,w;i<=m;i++)
scanf("%d%d%d",&u,&v,&w);
e[i]=edge(u,v,w,i);
for(int i=1;i<=n;i++)
fa[i]=i;
sort(e+1,e+m+1);
for(int i=1;i<=m;i++)
if(unifa(e[i].u,e[i].v))
vis[e[i].id]=1;
addedge(e[i].u,e[i].v,e[i].w);
addedge(e[i].v,e[i].u,e[i].w);
dep[1]=1;dfs(1,0);
for(int i=1;i<=m;i++)
if(!vis[e[i].id])
ans[e[i].id]=query(e[i].u,e[i].v);
for(int i=1;i<=m;i++)
if(!vis[i])
printf("%d\n",ans[i]);
return 0;
CF1184 E3
以上是关于Helvetic Coding Contest 2019的主要内容,如果未能解决你的问题,请参考以下文章
nowcoder 207G - Coding Contest - [最小费用最大流]
HDU5988 - 2016icpc青岛 - G - Coding Contest 费用流(利用对数化乘为加
Coding Contest HDU - 5988(费用流)