Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest

比赛链接:

http://codeforces.com/gym/100676

题目链接:

http://codeforces.com/gym/100676/attachments/download/3333/acm-arabella-collegiate-programming-contest-en.pdf


A. Relational Operator

直接模拟,复杂度O(1)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    int a,b;
    char c[5];
    while(T--)
    {
        scanf("%d%s%d",&a,c,&b);
        if(strlen(c)==1)
        {
            if(c[0]=='<')printf("%s\n",(a<b ? "true" : "false"));
            else printf("%s\n",(a>b ? "true" : "false"));
        }
        else
        {
            if(c[0]=='!')printf("%s\n",(a!=b ? "true" : "false"));
            else if(c[0]=='=')printf("%s\n",(a==b ? "true" : "false"));
            else if(c[0]=='<')printf("%s\n",(a<=b ? "true" : "false"));
            else printf("%s\n",(a>=b ? "true" : "false"));
        }
    }
    return 0;
}

B. Three Angles

判断三个角度是否均为正且和为180即可,复杂度O(1)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int main()
{
    int T;
    scanf("%d",&T);
    int a,b,c;
    while(T--)
    {
        scanf("%d%d%d",&a,&b,&c);
        printf("%s\n",(a>0 && b>0 && c>0 && a+b+c==180 ? "YES" : "NO"));
    }
    return 0;
}

C. Memory is Full

贪心,先移除占用内存较大的软件,复杂度O(nlogn)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
using namespace std;
int a[105];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int k,m,n;
        scanf("%d%d%d",&k,&m,&n);
        int sum=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            sum+=a[i];
        }
        int emp=k-sum;
        if(emp>=m)
        {
            printf("0\n");
            continue;
        }
        sort(a+1,a+n+1,greater<int>());
        for(int i=1;i<=n;i++)
        {
            emp+=a[i];
            if(emp>=m)
            {
                printf("%d\n",i);
                break;
            }
        }
    }
    return 0;
}

D. Sudoku

直接模拟,复杂度O(1)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
char s[15][15];
bool vis[15];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        for(int i=0;i<9;i++)scanf("%s",s[i]);
        bool isok=1;
        for(int i=0;i<9;i++)
        {
            bool flag=1;
            memset(vis,0,sizeof(vis));
            for(int j=0;j<9;j++)vis[s[i][j]-'1']=1;
            for(int j=0;j<9;j++)flag&=vis[j];
            isok&=flag;
        }
        for(int i=0;i<9;i++)
        {
            bool flag=1;
            memset(vis,0,sizeof(vis));
            for(int j=0;j<9;j++)vis[s[j][i]-'1']=1;
            for(int j=0;j<9;j++)flag&=vis[j];
            isok&=flag;
        }
        for(int i=0;i<9;i+=3)
            for(int j=0;j<9;j+=3)
            {
                memset(vis,0,sizeof(vis));
                for(int p=i;p<i+3;p++)
                    for(int q=j;q<j+3;q++)
                        vis[s[p][q]-'1']=1;
                bool flag=1;
                for(int p=0;p<9;p++)flag&=vis[p];
                isok&=flag;
            }
        printf("%s\n",(isok ? "Valid" : "Invalid"));
    }
    return 0;
}

E. Time Limit Exceeded?

记下每个数出现的次数,维护前缀和后可以O(1)计算每个数作为较小数时的贡献,复杂度O(n)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
int cnt[10005],pre[10005];
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n;
        scanf("%d",&n);
        int in;
        memset(cnt,0,sizeof(cnt));
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&in);
            cnt[in]++;
        }
        for(int i=1;i<=10000;i++)pre[i]=pre[i-1]+cnt[i];
        int ans=0;
        for(int i=1;i<=10000;i++)
        {
            ans+=cnt[i]*(cnt[i]-1)/2;
            ans+=cnt[i]*(pre[min(10000,i+31)]-pre[i]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

F. Palindrome

若s[i]与s[j]相同,则将s[i]与s[j]合并到同一集合中,并选取集合的代表元素,可以利用并查集维护,

在选取代表元素时,若集合中只有"?",则选"?"为代表元素,否则任意选取一个不为"?"的字符,

完成合并过程后,逐个检查元素及其代表元素是否一致,并统计元素全为"?"的集合个数,复杂度O(nlogn)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<string>
using namespace std;
const int MAXN=50005;
const int Mod=1000000007;
int fast_pow(int a,int k)
{
    int res=1;
    while(k>0)
    {
        if(k&1)res=1LL*res*a%Mod;
        a=1LL*a*a%Mod;
        k>>=1;
    }
    return res;
}
char s[MAXN];
int p[MAXN];
bool vis[MAXN];
void Init(int n)
{
    for(int i=0;i<n;i++)p[i]=i;
}
int Find(int x)
{
    return x==p[x] ? x : p[x]=Find(p[x]);
}
void Union(int x,int y)
{
    x=Find(x);
    y=Find(y);
    if(x==y)return;
    if(s[x]=='?')p[x]=y;
    else p[y]=x;
}
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        int n,m;
        scanf("%d%d",&n,&m);
        scanf("%s",s);
        Init(n);
        for(int i=0;i<n/2;i++)
            Union(i,n-1-i);
        int x,y;
        while(m--)
        {
            scanf("%d%d",&x,&y);
            Union(x-1,y-1);
        }
        bool isok=1;
        int cnt=0;
        memset(vis,0,sizeof(vis));
        for(int i=0;i<n;i++)
        {
            int t=Find(i);
            if(s[t]=='?')
            {
                if(!vis[t])
                {
                    vis[t]=1;
                    cnt++;
                }
            }
            else isok&=(s[t]==s[i] || s[i]=='?');
        }
        if(isok)printf("%d\n",fast_pow(26,cnt));
        else printf("0\n");
    }
    return 0;
}

G. Training Camp

状压dp,用dp[s]表示选取了s集合的最大收益,

根据拓扑序检验状态合法性并进行转移即可,复杂度O(n*2^n)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<sstream>
#include<algorithm>
#include<string>
#include<vector>
#include<map>
using namespace std;
map<string,int>mp;
string s[25];
int w[25],dp[1<<18];
vector<pair<int,int> >e;
bool used[25],in[25];
void init()
{
    e.clear();
    mp.clear();
}
int main()
{
    ios::sync_with_stdio(false);
    stringstream ss;
    int T;
    cin>>T;
    while(T--)
    {
        int n,m;
        cin>>n>>m;
        string str;
        getline(cin,str);
        init();
        for(int i=1;i<=n;i++)
        {
            w[i]=0;
            getline(cin,str);
            ss.clear();
            ss.str(str);
            string name="",word="";
            while(ss>>word)
            {
                if(word[0]>='0' && word[0]<='9')
                    for(int j=0;j<word.size();j++)
                        w[i]=w[i]*10+word[j]-'0';
                else name+=word+" ";
            }
            mp[name]=i;
        }
        /*
        for(int i=1;i<=n;i++)
            cout<<s[i]<<" "<<w[i]<<endl;
        */
        for(int i=1;i<=m;i++)
        {
            getline(cin,str);
            ss.clear();
            ss.str(str);
            string name="",word="";
            int st,ed;
            while(ss>>word)
            {
                if(word[0]=='-')
                {
                    st=mp[name];
                    name.clear();
                }
                else name+=word+" ";
            }
            ed=mp[name];
            e.push_back(make_pair(st,ed));
        }
        memset(dp,0,sizeof(dp));
        for(int mask=0;mask<(1<<n);mask++)
        {
            memset(used,0,sizeof(used));
            int day=1;
            for(int i=0;i<n;i++)
                if(mask&(1<<i))
                {
                    day++;
                    used[i+1]=1;
                }
            bool isok=1;
            for(int i=0;i<e.size();i++)
                if(!used[e[i].first] && used[e[i].second])
                {
                    isok=0;
                    break;
                }
            if(!isok)continue;
            memset(in,0,sizeof(in));
            for(int i=0;i<e.size();i++)
                if(!used[e[i].first])
                    in[e[i].second]=1;
            for(int i=0;i<n;i++)
                if(!used[i+1] && !in[i+1])
                    dp[mask|(1<<i)]=max(dp[mask|(1<<i)],dp[mask]+day*w[i+1]);
        }
        cout<<dp[(1<<n)-1]<<endl;
    }
    return 0;
}

H. Capital City

双连通分量缩点,对得到的树进行两次bfs得到直径,然后枚举直径上的点求出重心,

考虑到可能有重边以及自环,需要进行去重,

去重时利用并查集维护,如果两个点之间有多条路径,则将这两个点合并为一个点,

由于要输出最小的标号,还需要选取每个集合中标号最小的点作为代表元素,复杂度O(nlogn+mlogm)。

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<vector>
#include<set>
#include<queue>
#include<stack>
using namespace std;
typedef long long ll;
const int MAXN=100005;
const int MAXM=400005;
const int INF=0x3f3f3f3f;
//BCC
struct Edge
{
    int to,next,cost;
    bool cut;
}edge[MAXM];
int head[MAXN],tot;
int Low[MAXN],DFN[MAXN],Stack[MAXN],Belong[MAXN];
int Get[MAXN];
int Index,top;
int block;
bool Instack[MAXN];
int bridge;
void addedge(int u,int v,int cost)
{
    edge[tot].to=v;
    edge[tot].next=head[u];
    edge[tot].cut=0;
    edge[tot].cost=cost;
    head[u]=tot++;
}
void Tarjan(int u,int pre)
{
    int v;
    Low[u]=DFN[u]=++Index;
    Stack[top++]=u;
    Instack[u]=1;
    for(int i=head[u];i!=-1;i=edge[i].next)
    {
        v=edge[i].to;
        if(v==pre)continue;
        if(!DFN[v])
        {
            Tarjan(v,u);
            if(Low[u]>Low[v])Low[u]=Low[v];
            if(Low[v]>DFN[u])
            {
                bridge++;
                edge[i].cut=1;
                edge[i^1].cut=1;
            }
        }
        else if(Instack[v] && Low[u]>DFN[v])
            Low[u]=DFN[v];
    }
    if(Low[u]==DFN[u])
    {
        block++;
        do
        {
            v=Stack[--top];
            Instack[v]=0;
            Belong[v]=block;
        }
        while(v!=u);
    }
}
void init()
{
    tot=0;
    memset(head,-1,sizeof(head));
}
void get_BCC(int n)
{
    memset(DFN,0,sizeof(DFN));
    memset(Instack,0,sizeof(Instack));
    Index=top=block=bridge=0;
    Tarjan(1,0);
    memset(Get,INF,sizeof(Get));
    for(int i=1;i<=n;i++)
        Get[Belong[i]]=min(Get[Belong[i]],i);
}
//DSU
int p[MAXN];
void DSU_Init(int n)
{
    for(int i=1;i<=n;i++)p[i]=i;
}
int DSU_Find(int x)
{
    return x==p[x] ? x : p[x]=DSU_Find(p[x]);
}
void DSU_Union(int x,int y)
{
    x=DSU_Find(x);
    y=DSU_Find(y);
    if(x==y)return;
    p[x]=y;
}
void DSU_Compress(int n)
{
    for(int i=1;i<=n;i++)p[i]=DSU_Find(i);
}
//InputData
struct Input
{
    int u,v,cost;
    Input(){}
    Input(int _u,int _v,int _cost)
    {
        if(_u>_v)swap(_u,_v);
        u=_u;
        v=_v;
        cost=_cost;
    }
    bool operator < (const Input &t)const
    {
        return v==t.v ? u<t.u : v<t.v;
    }
};
set<Input>s;
int vis[MAXN];
int Stand[MAXN];
//Tree
vector<pair<int,int> >e[MAXN];
void Prepare(int n)
{
    for(int i=1;i<=n;i++)e[i].clear();
    for(int i=1;i<=n;i++)
        for(int j=head[i];j!=-1;j=edge[j].next)
            if(edge[j].cut)
            {
                e[Belong[i]].push_back(make_pair(Belong[edge[j].to],edge[j].cost));
                e[Belong[edge[j].to]].push_back(make_pair(Belong[i],edge[j].cost));
            }
}
pair<int,int> pre[MAXN];
ll dis[MAXN];
int BFS(int st)
{
    for(int i=1;i<=block;i++)dis[i]=(1LL<<62)-1;
    queue<int>q;
    q.push(st);
    pre[st].first=pre[st].second=-1;
    dis[st]=0;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<e[u].size();i++)
        {
            int v=e[u][i].first;
            int c=e[u][i].second;
            if(dis[v]>dis[u]+c)
            {
                q.push(v);
                dis[v]=dis[u]+c;
                pre[v]=make_pair(u,c);
            }
        }
    }
    int loc=st;
    ll Max=0;
    for(int i=1;i<=block;i++)
        if(dis[i]>Max)
        {
            loc=i;
            Max=dis[i];
        }
    return loc;
}
//Main
int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        init();
        int n,m;
        scanf("%d%d",&n,&m);
        DSU_Init(n);
        s.clear();
        int a,b,c;
        for(int i=1;i<=m;i++)
        {
            scanf("%d%d%d",&a,&b,&c);
            if(a==b)continue;
            Input t=Input(DSU_Find(a),DSU_Find(b),c);
            if(s.find(t)==s.end())s.insert(t);
            else DSU_Union(a,b);
        }
        DSU_Compress(n);
        int cnt=0;
        memset(Stand,INF,sizeof(Stand));
        memset(vis,0,sizeof(vis));
        for(int i=1;i<=n;i++)
        {
            int t=DSU_Find(i);
            if(!vis[t])vis[t]=++cnt;
            Stand[vis[t]]=min(Stand[vis[t]],i);
        }
        set<Input>::iterator itr;
        for(itr=s.begin();itr!=s.end();itr++)
        {
            Input t=*itr;
            int t1=DSU_Find(t.u);
            int t2=DSU_Find(t.v);
            if(t1==t2)continue;
            else
            {
                addedge(vis[t1],vis[t2],t.cost);
                addedge(vis[t2],vis[t1],t.cost);
            }
        }
        get_BCC(cnt);
        Prepare(cnt);
        int end1=BFS(1);
        int end2=BFS(end1);
        ll len=dis[end2];
        stack<pair<int,ll> >sst;
        ll now=0;
        sst.push(make_pair(end2,max(now,len-now)));
        for(int i=end2;i!=end1 && i!=-1;i=pre[i].first)
        {
            now+=pre[i].second;
            ll t=max(now,len-now);
            while(!sst.empty() && t<sst.top().second)sst.pop();
            if(sst.empty() || t==sst.top().second)sst.push(make_pair(pre[i].first,t));
        }
        int ans_loc=INF;
        ll ans_pat=sst.top().second;
        while(!sst.empty())
        {
            ans_loc=min(ans_loc,Stand[Get[sst.top().first]]);
            sst.pop();
        }
        printf("%d %I64d\n",ans_loc,ans_pat);
    }
    return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值