Helvetic Coding Contest 2019

题目链接:戳我

小注:其中部分(大括号不换行的)代码是BLUESKY007神仙写的。

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
",i,calc(i));
            return 0;
        }
    }
    printf("NO
");
    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
",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])]," 
"[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 Node{int 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
",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,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
",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
",__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
",ans[i]);
		}
	}
	return 0;
}

CF1184 E3

#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk make_pair
#define fi first
#define se second
 
using namespace std;
 
const int N=1e6+6;
 
int n,m,fa[N],afa[N],dep[N],eid[N];
 
vector<int>G[N],W[N],wid[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;
}
 
int afind(int u){
	return afa[u]==u?afa[u]:afa[u]=afind(afa[u]);
}
 
bool aunifa(int u,int v){
	if(afind(u)==afind(v)){
		return 0;
	}
	afa[afind(u)]=afind(v);
	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,int id){
	G[u].push_back(v);W[u].push_back(w);wid[u].push_back(id);
}
 
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;
		eid[v]=wid[u][i];
		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]=afa[i]=i;ans[i]=1e9;
	}
	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,e[i].id);
			addedge(e[i].v,e[i].u,e[i].w,e[i].id);
		}
	}
	dep[1]=1;dfs(1,0);
	for(int i=1,l,u,v;i<=m;i++){
		if(!vis[e[i].id]){
			ans[e[i].id]=query(e[i].u,e[i].v);
			l=lca(e[i].u,e[i].v).fi;
			u=afind(e[i].u);v=afind(e[i].v);
			while(dep[u]>dep[l]){
				if(aunifa(u,jump[u][0])){
					ans[eid[u]]=e[i].w;
				}
				u=afind(jump[u][0]);
			}
			while(dep[v]>dep[l]){
				if(aunifa(v,jump[v][0])){
					ans[eid[v]]=e[i].w;
				}
				v=afind(jump[v][0]);
			}
		}
	}
	for(int i=1;i<=m;i++){
		printf("%d
",ans[i]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/fengxunling/p/11148850.html