比赛地址

Codeforces Gym

Rank:26/95

[A] Environment-Friendly Travel

题意

给出一个图,求起点到终点的所有路径中,不超过距离b的花费最小的路径是多少.每条路的花费和路径长度并不相同.

题解

考虑对Dijkstra进行一下改进,用dis[i][j]表示从起点到点i的长度恰好为j的路径中,最少的花费是多少.然后堆里的元素同时维护点的编号,花费,以及起点到该点的路径长度.用改进后的Dijkstra跑一遍就行了.

代码

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<queue>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define IL inline
#define reg register
#define LL long long
#define N 1010
#define INF 0x3f3f3f3f
using namespace std;

int T,n,b,i,j,lsum=1,l,p,q;
int c[N],x[N],y[N],head[N];
int dis[N][N];

typedef pair<int,int> pi;

vector <pi> a[N];
priority_queue <pair<int,pair<int,int> > > Q;

struct Edge{
    int t,next,l,c;
}e[N*N*8];

IL int Abs(int x){return (x<0)?-x:x;}
IL void Swap(int &a,int &b){a^=b^=a^=b;}
IL int Min(int a,int b){return (a<b)?a:b;}
IL int Max(int a,int b){return (a>b)?a:b;}

IL int read(){
    int p=0,f=1;    char    c=getchar();
    while (c<48||c>57)  {if (c=='-')    f=-1;   c=getchar();}
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p*f;
}

inline void Add(int s,int t,int l,int cost){
    e[lsum].t=t;    e[lsum].l=l;    e[lsum].next=head[s];   e[lsum].c=cost; head[s]=lsum++; 
}

IL int Dis(int i,int j){
    return ceil(sqrt(pow(x[i]-x[j],2)+pow(y[i]-y[j],2)));
}

IL void Ready(){
    reg int i=0,d=0;
    for (i=1;i<=n;i++)
        for (auto j : a[i]){
            d=Dis(i,j.first)*c[j.second];
            Add(i,j.first,d,Dis(i,j.first));    Add(j.first,i,d,Dis(i,j.first));
        }
    for (i=1;i<=n;i++){
        Add(0,i,Dis(0,i)*c[0],Dis(0,i));
        Add(i,0,Dis(0,i)*c[0],Dis(0,i));
        Add(1001,i,Dis(1001,i)*c[0],Dis(1001,i));
        Add(i,1001,Dis(1001,i)*c[0],Dis(1001,i));
    }
    Add(0,1001,Dis(0,1001)*c[0],Dis(1001,0));
    Add(1001,0,Dis(0,1001)*c[0],Dis(1001,0));
}

IL void Work(){
    reg int i=0,Ans=INF,p=0,q=0;
    if (Dis(0,1001)>b){
        puts("-1");
        return;
    }
    memset(dis,INF,sizeof(dis));
    dis[0][0]=0;
    Q.push(make_pair(0,make_pair(0,0)));
    while (!Q.empty()){
        pair<int,pair<int,int>> s=Q.top();
        Q.pop();
        p=s.second.first;   q=s.second.second;
        for (i=head[p];i;i=e[i].next){
            if (q+e[i].c>b) continue;
            if (e[i].l-s.first<dis[e[i].t][q+e[i].c]){
                dis[e[i].t][q+e[i].c]=e[i].l-s.first;
                Q.push(make_pair(-dis[e[i].t][q+e[i].c],make_pair(e[i].t,q+e[i].c)));
            }
        }
    }
    for (i=0;i<=b;i++)
        Ans=Min(Ans,dis[1001][i]);
    cout<<Ans<<endl;
}

int main(){
    #ifdef __Marvolo
    freopen("zht.in","r",stdin);
    freopen("zht.out","w",stdout);
    #endif
    x[0]=read();    y[0]=read();
    x[1001]=read(); y[1001]=read();
    b=read();   c[0]=read();    T=read();
    for (i=1;i<=T;i++)  c[i]=read();
    n=read();
    for (i=1;i<=n;i++){
        x[i]=read();    y[i]=read();
        l=read();
        for (j=1;j<=l;j++){
            p=read()+1; q=read();
            a[i].push_back(make_pair(p,q));
        }
    }
    Ready();    Work();
    return 0;
}

[B] Biodiversity

题意&题解

签到题

代码

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define IL inline
#define reg register
#define LL long long
#define N 25 
#define INF 0x3f3f3f3f
using namespace std;

int i,n,Ans=0,flag=0;
string c,s;

map <string,int> M;

IL int Abs(int x){return (x<0)?-x:x;}
IL void Swap(int &a,int &b){a^=b^=a^=b;}
IL int Min(int a,int b){return (a<b)?a:b;}
IL int Max(int a,int b){return (a>b)?a:b;}

IL void FAST_IO() {ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);}

IL int read(){
    int p=0,f=1;    char    c=getchar();
    while (c<48||c>57)  {if (c=='-')    f=-1;   c=getchar();}
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p*f;
}

int main(){
    #ifdef __Marvolo
    freopen("zht.in","r",stdin);
    freopen("zht.out","w",stdout);
    #endif
    FAST_IO();
    cin>>n;
    for (i=1;i<=n;i++){
        cin>>c;
        M[c]+=1;
    }
    for (auto j : M){
        if (j.second>(n-j.second)){
            Ans=j.second;
            s=j.first;
            flag=1;
        }
    }
    if (!flag)  cout<<"NONE";
    else cout<<s<<endl;
    return 0;
}

[C] Ants

题意&题解

签到题

代码

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
int u[10000005];
char s[105];
int main() {
    int n; cin >> n;
    for (int i = 1; i <= n; i++) {
        scanf("%s", s);
        int len = strlen(s);
        if (len >= 7 || s[0] == '-') continue;
        int a = 0;
        for (int j = 0; j < len; j++)
            a = a * 10 + s[j] - '0';
        u[a] = 1;
    }
    for (int i = 0; i <= 1000000; i++) if (u[i] == 0) {
        printf("%d", i);
        return 0;
    }
    return 0;
}

[F] Icebergs

题意&题解

签到题

代码

#include <stdio.h>
#include <algorithm>
#include <vector>

#define LL long long

struct Po{LL x, y;} a[12345];

int main()
{
    int n;
    scanf("%d", &n);
    double ans = 0;
    while (n--)
    {
        int m;
        scanf("%d", &m);
        for (int i=0; i<m; ++i)
            scanf("%lld%lld", &a[i].x, &a[i].y);
        LL s = 0;
        for (int i=0; i<m; ++i)
            s += a[i].x*a[(i+1)%m].y - a[i].y*a[(i+1)%m].x;
        s = s >= 0 ? s : -s;
        ans += s / 2.0;
    }
    printf("%lld", (LL)ans);
    return 0;
}

[G] Swapping Places

题意

s种动物,每一个动物有一个名字,同时这些动物之间有l对朋友关系(没有传递性).然后给出一个长度为n的动物序列,要求通过任意次数的交换相邻两个动物位置的操作,使得这个序列的字典序最小.交换的条件是被交换的两个动物必须有朋友关系.求最后的交换结果是什么.

题解

首先将每种动物的位置单独存起来,维护一个类似于链表的东西.同时预处理一下每一种动物的表头(也就是排在最前面的那个动物),它的前面有几个动物和它有朋友关系,这个值记为s[i].之后开始枚举最终结果的每一位,按照字典序从小到大枚举动物.假如说一种动物的表头和在它之前的所有动物都有朋友关系,说明它可以通过交换操作换到最前面.记录答案,然后去维护剩下动物的表头的信息.

假如说该动物的位置是i,其他动物的表头的位置是j.如果 i , 那么++s[j].如果 i > j ,就把原序列第i个位置的动物替换为和所有动物都有朋友关系的一个特殊的动物.同时,一个链表的表头发生了变化,再根据原序列暴力维护.这样整个序列至多被扫描s次.总的时间复杂度为O(ns)

代码

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<queue>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define IL inline
#define reg register
#define LL long long
#define INF 0x3f3f3f3f
#define N 100010
#define NM 210
using namespace std;

int s,l,n,i,p,q,tail=0;
int L[NM][NM];
int sum[NM],a[N],Ans[N];
string c[NM],x,y;

map <int,string> M;
map <string,int> F;

priority_queue <int> Q;

IL void FAST_IO() {ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);}

IL int Abs(int x){return (x<0)?-x:x;}
IL void Swap(int &a,int &b){a^=b^=a^=b;}
IL int Min(int a,int b){return (a<b)?a:b;}
IL int Max(int a,int b){return (a>b)?a:b;}

IL int read(){
    int p=0,f=1;    char    c=getchar();
    while (c<48||c>57)  {if (c=='-')    f=-1;   c=getchar();}
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p*f;
}

struct Data{
    int tot=0,sum=0,head=0,w=0;
    vector <int> a;
}t[NM];

IL void Ready(){
    reg int i=0,x=0,j=0;
    for (i=1;i<=n;i++){
        t[a[i]].a.push_back(i);
        t[a[i]].sum++;
    }
    for (i=1;i<=s;i++){
        if (t[i].sum==0)    continue;
        x=t[i].a[t[i].head];
        t[i].w=x;
        for (j=1;j<=x;j++)
            if (L[a[j]][i]) t[i].tot++;
    }
}

IL void Work(){
    reg int i=0,j=0,k=0,x=0,y=0;
    for (i=1;i<=n;i++){
        for (j=1;j<=s;j++){
            if (t[j].tot!=t[j].w)   continue;
            Ans[i]=j;   break;
        }
        a[t[j].w]=INF;
        for (k=1;k<=s;k++){
            if (k==j)   continue;
            if (t[j].w<t[k].w){
                if (!L[j][k])   t[k].tot++;
                continue;
            }
        }
        x=t[j].w+1; t[j].head++;    t[j].w=INF;
        if (t[j].head>=t[j].sum)    continue;
        t[j].w=y=t[j].a[t[j].head];
        for (k=x;k<=y;k++){
            if (a[k]==INF)  t[j].tot++;
            else if (L[a[k]][j])    t[j].tot++;
        }
    }
    for (i=1;i<=n;i++)
        cout<<M[Ans[i]]<<" ";
}

int main(){
    #ifdef __Marvolo
    freopen("zht.in","r",stdin);
    freopen("zht.out","w",stdout);
    #endif
    FAST_IO();
    cin>>s>>l>>n;
    for (i=1;i<=s;i++)  cin>>c[i];
    sort(c+1,c+1+s);
    for (i=1;i<=s;i++)  M[i]=c[i],F[c[i]]=i;
    for (i=1;i<=l;i++){
        cin>>x>>y;
        p=F[x]; q=F[y];
        L[p][q]=L[q][p]=1;
    }
    for (i=1;i<=s;i++)  L[i][i]=1;
    for (i=1;i<=n;i++){
        cin>>x; a[i]=F[x];
    }
    if (!l) {
        for (i=1;i<=n;i++)  cout<<M[a[i]]<<" ";
        return 0;
    }
    if (n==1){
        cout<<M[a[1]];  return 0;
    }
    Ready();    Work();
    return 0;
}

[I] Rats

题意&题解

签到题

代码

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define IL inline
#define reg register
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;

double n1,n2,n12;

IL int Abs(int x){return (x<0)?-x:x;}
IL void Swap(int &a,int &b){a^=b^=a^=b;}
IL int Min(int a,int b){return (a<b)?a:b;}
IL int Max(int a,int b){return (a>b)?a:b;}

IL int read(){
    int p=0,f=1;    char    c=getchar();
    while (c<48||c>57)  {if (c=='-')    f=-1;   c=getchar();}
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p*f;
}

int main(){
    #ifdef __Marvolo
    freopen("zht.in","r",stdin);
    freopen("zht.out","w",stdout);
    #endif
    scanf("%lf%lf%lf",&n1,&n2,&n12);
    printf("%lld\n",(LL)((n1+1)*(n2+1)/(n12+1)-1+0.00005));
    return 0;
}

[K] Birdwatching

题意

给出一个有向图和一个点t.求t直接相连的点中有多少个满足以下条件:把t到该点的边去掉,则t无法再到达这个点.

题解

删掉所有和t相连的边,然后其他所有边反向.每一个点开一个set用来记录能被哪些和t直接相连的点访问过.然后依次从和t相邻的点开始DFS.假如说a能够从b经过一些点访问到,那么在原图中,一定有一条从ta,再从ab的路径,所以b就不符合题意.在DFS完成后据此就可以得到答案.

代码

#include<cstring>
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<vector>
#include<cmath>
#include<map>
#include<set>
#define l(x) (x<<1)
#define r(x) ((x<<1)+1)
#define IL inline
#define reg register
#define LL long long
#define N 100010
#define INF 0x3f3f3f3f
using namespace std;

int n,m,t,i,x,y,lsum=1;
int head[N];

vector <int> b,Ans;
set <int> f[N];

struct Edge{
    int t,next;
}e[N*8];

IL int Abs(int x){return (x<0)?-x:x;}
IL void Swap(int &a,int &b){a^=b^=a^=b;}
IL int Min(int a,int b){return (a<b)?a:b;}
IL int Max(int a,int b){return (a>b)?a:b;}

IL int read(){
    int p=0,f=1;    char    c=getchar();
    while (c<48||c>57)  {if (c=='-')    f=-1;   c=getchar();}
    while (c>=48&&c<=57)    p=(p<<1)+(p<<3)+c-48,c=getchar();
    return p*f;
}

inline void Add(int s,int t){
    e[lsum].t=t;    e[lsum].next=head[s];   head[s]=lsum++;
}

IL void Dfs(int x,int pre){
    reg int i=0;
    if (f[x].size()>1 || f[x].count(pre))   return;
    f[x].insert(pre);
    for (i=head[x];i;i=e[i].next)   Dfs(e[i].t,pre);
}

int main(){
    #ifdef __Marvolo
    freopen("zht.in","r",stdin);
    freopen("zht.out","w",stdout);
    #endif
    n=read();   m=read();   t=read()+1;
    for (i=1;i<=m;i++){
        x=read()+1; y=read()+1;
        if (y==t){
            b.push_back(x); continue;
        }
        Add(y,x);
    }
    for (auto j : b)    Dfs(j,j);
    for (auto j : b)
        if (f[j].size()==1) Ans.push_back(j);
    sort(Ans.begin(),Ans.end());
    cout<<Ans.size()<<endl;
    for (auto j : Ans)
        printf("%d\n",j-1);
    return 0;
}

总结

这场中第一次碰到了无榜可跟的情况,导致中间产生了一段空档期.中期多线开题感觉精力有些分散.除了硬开了一道G题之外(居然还拿了一血),后面都只写了一些残篇,尤其在打表找规律上浪费了过多的时间.然后喂题的时候一定要再确认下核心题意,最近两场比赛都栽在这上面了.

最后吐槽一下政治正确害人不浅,欧洲赛区的题目居然非要套上一个环保的题目背景,有的还套的很生硬,导致题面又臭又长.下次不拿欧洲的题来练了.

说点什么
支持Markdown语法
好耶,沙发还空着ヾ(≧▽≦*)o
Loading...