Codeforces Gym 2015 ACM Arabella Collegiate Programming Contest

来源:互联网 发布:linux设置ip地址命令 编辑:程序博客网 时间:2024/05/01 19:44

比赛链接:

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;//BCCstruct 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);}//DSUint 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);}//InputDatastruct 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];//Treevector<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;}//Mainint 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
原创粉丝点击