2013-2014 ACM-ICPC Brazil Subregional Programming Contest

A.
题意:给A,B,C三个数,A,B,C ∈ {0,1},如果A,B,C中有一个与其他两个不一样,则输出其标号。不存在则输出’*’
题解:模拟

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define LiangJiaJun main
using namespace std;
int a,b,c;
int LiangJiaJun(){
    cin>>a>>b>>c;
    if(a!=b&&a!=c)return puts("A"),0;
    if(b!=a&&b!=c)return puts("B"),0;
    if(c!=a&&c!=b)return puts("C"),0;
    puts("*");
    return 0;
}

D.
题意:给两个数列,问第一个数列能否经过翻折变成第二个数列,翻折后重叠的格子的数值是直接相加。
题解:暴力dfs

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define LiangJiaJun main
using namespace std;
int n,m;
int a[24],b[24],ta[24];
bool check(int len){
     bool l1=0,l2=0;
     for(int i=1;i<=len;i++)if(ta[i]!=b[i])l1=1;
     for(int i=1;i<=len;i++)if(ta[i]!=b[len-i+1])l2=1;
     if(l1&&l2)return 0;return 1;
}
bool flag=0;
int l,r,sv;
void dfs(int cur,int len){
     if(flag)return;
     if(len<m)return;
     if(len==m){
        if(check(len)){
            puts("S");flag=1;
        }
        return;
     }
     int tta[24];
     for(int i=1;i<len;i++){
         l=i,r=len-i;
         for(int j=1;j<=len;j++)tta[j]=ta[j];
         if(l<r){
            for(int k=i,g=i+1;k&&g<=len;k--,g++)ta[g]+=ta[k];
            for(int j=1;j<=r;j++)ta[j]=ta[j+l];
         }
         else{
            for(int k=i,g=i+1;k&&g<=len;k--,g++)ta[k]+=ta[g];
         }

         sv=max(l,r);
         dfs(cur+1,sv);
         for(int j=1;j<=len;j++)ta[j]=tta[j];
     }
}

int LiangJiaJun(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    scanf("%d",&m);
    for(int i=1;i<=m;i++)scanf("%d",&b[i]);
    for(int i=1;i<=n;i++)ta[i]=a[i];
    if(n==m){
        if(check(n))puts("S");
        else puts("N");
        return 0;
    }
    dfs(1,n);
    if(!flag)puts("N");
    return 0;
}

E.
题意:第一行两个数n,r,表示开始是n个潜水员下水,回来时候是r个,求问没回来的潜水员的编号
题解:模拟

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#include<queue>
#define LiangJiaJun main
using namespace std;
int pd[10004],n,r;
bool q=0;
int LiangJiaJun(){
    memset(pd,0,sizeof(pd));
    scanf("%d%d",&n,&r);
    for(int i=1;i<=r;i++){
        int x;scanf("%d",&x);
        pd[x]=1;
    }
    for(int i=1;i<=n;i++)if(!pd[i])printf("%d ",i),q=1;
    if(!q)printf("*");
    puts("");
    return 0;
}

F.
题意:一个圆上有n个点将圆分割成n段线段,给你那n条线段的长度,求问那些点能够成多少个等边三角形
题解:二分裸题…..设全部线段长度总和为d,那么能够构成等边三角形的三个点中任意两点之间的劣弧长度一定为d/3

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define LiangJiaJun main
using namespace std;
int n,a[100004];
int ans=0,lp=0;
int erfen(int L,int R,int x){
    int mid,l=L,r=R;
    while(l<=r){
        mid=(l+r)>>1;
        if(a[mid]==x)return mid;
        if(a[mid]<x)l=mid+1;
        else r=mid-1;
    }
    return -1;
}
int LiangJiaJun(){
    scanf("%d",&n);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=2;i<=n;i++)a[i]+=a[i-1];
    lp=a[n]/3;
    for(int i=1;i<=n;i++){
        int s1,s2,s3;
        s1=i;
        s2=erfen(s1+1,n,a[s1]+lp);
        if(s2==-1)continue;
        s3=erfen(s2+1,n,a[s2]+lp);
        if(s3==-1)continue;
        ++ans;
    }
    printf("%d\n",ans);
    return 0;
}

J.
题意:NOIP2013货车运输

#include<iostream>
#include<cstring>
#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define INF 1999122700
#define LiangJiaJun main
using namespace std;
int n,m,s;
struct data{int u,v,w;}a[100004];
struct edge{int to,nt,w;}e[250004];
inline bool dex(data A,data B){return A.w > B.w;}
int f[20004];
int Find(int x){return (f[x]==x)?f[x]:f[x]=Find(f[x]);}
int h[20004],ne=1;
int fa[20004][34],d[20004][34],depth[20004];

void add(int u,int v,int w){
     e[++ne].to=v;e[ne].nt=h[u];h[u]=ne;
     e[ne].w=w;
}
void kruskal(){
     for(int i=1;i<=n;i++)f[i]=i;
     int tot=0;
     for(int i=1;i<=m;i++){
         int p=Find(a[i].u),q=Find(a[i].v);
         if(p!=q){
            f[p]=q;
            add(a[i].u,a[i].v,a[i].w);
            add(a[i].v,a[i].u,a[i].w);
         }
     }
}
void dfs(int x){
     for(int i=1;fa[fa[x][i-1]][i-1];i++){
         fa[x][i]=fa[fa[x][i-1]][i-1];
         d[x][i]=min(d[x][i-1],d[fa[x][i-1]][i-1]);
     }
     for(int i=h[x];i;i=e[i].nt){
         if(!depth[e[i].to]){
             depth[e[i].to]=depth[x]+1;
             fa[e[i].to][0]=x;
             d[e[i].to][0]=e[i].w;
             dfs(e[i].to);
         }
     }
}
int lca(int u,int v){
    if(depth[u]<depth[v])swap(u,v);
    int dva=(depth[u]-depth[v]);
    for(int i=0;i<=17;i++)if(dva&(1<<i))u=fa[u][i];
    if(u==v)return u;
    for(int i=17;i>=0;i--){
        if(fa[u][i]!=fa[v][i]){
            u=fa[u][i];
            v=fa[v][i];
        }
    }
    if(u==v)return u;
    return fa[u][0];
}
int query(int x,int f){
    int dva=depth[x]-depth[f],ans=INF;
    for(int i=0;i<=17;i++){
        if(dva&(1<<i)){
            ans=min(ans,d[x][i]);
            x=fa[x][i];
        }
    }
    return ans;
}
int LiangJiaJun(){
    memset(fa,0,sizeof(fa));
    memset(d,127/3,sizeof(d));
    scanf("%d%d%d",&n,&m,&s);
    for(int i=1;i<=m;i++)
        scanf("%d%d%d",&a[i].u,&a[i].v,&a[i].w);
    sort(a+1,a+m+1,dex);
    kruskal();
    for(int i=1;i<=n;i++){
        if(!depth[i]){
            depth[i]=1;
            dfs(i);
        }
    }
    for(int i=1;i<=s;i++){
        int x,y,t;
        scanf("%d%d",&x,&y);
        if(Find(x)!=Find(y))puts("0");
        t=lca(x,y);
        printf("%d\n",min(query(x,t),query(y,t)));
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
ACM-ICPC(国际大学生程序设计竞赛)是一项面向大学生的计算机编程竞赛,涉及算法和数据结构等领域。在比赛中,选手需要解决一系列编程问题,使用合适的算法和数据结构来实现正确和高效的解决方案。 对于整理ACM-ICPC模板,以下是一些建议: 1. 了解比赛要求:首先,你需要了解ACM-ICPC比赛的具体要求和规则。这包括了解比赛所涉及的算法和数据结构,以及题目的类型和难度等。 2. 收集资料:收集与ACM-ICPC相关的资料,包括经典算法和数据结构的实现代码、常见问题的解题思路等。可以参考教材、博客、论文等资源。 3. 整理模板:将收集到的资料整理成模板。可以按照算法和数据结构的分类进行整理,例如排序算法、图算法、字符串算法等。对每个模板,添加必要的注释和示例代码,以便理解和使用。 4. 测试代码:对每个模板编写测试代码,确保它们的正确性和可靠性。可以使用已知的测试用例或自行设计测试用例。 5. 更新与扩充:定期更新和扩充模板,以适应ACM-ICPC比赛中新出现的算法和数据结构。同时,根据自己的经验和理解,对模板进行优化和改进。 6. 练习和复习:在比赛之前,利用整理好的模板进行练习和复习。尝试解决一些经典问题,使用模板中的算法和数据结构进行实现,并进行优化。 希望这些建议对你整理ACM-ICPC模板有所帮助!

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值