Codeforces Round #101 (Div. 2)

--------------

A. Amusing Joke

--

前两行的字母恰好组成最后一行

--

#include <iostream>
#include <cstring>
using namespace std;

char a[1111];
int ch[26]={0};

int main()
{
    cin>>a;
    for (int i=0;a[i];i++){
        ch[a[i]-'A']++;
    }
    cin>>a;
    for (int i=0;a[i];i++){
        ch[a[i]-'A']++;
    }
    cin>>a;
    for (int i=0;a[i];i++){
        ch[a[i]-'A']--;
    }
    bool flag=true;
    for (int i=0;i<26;i++){
        if (ch[i]!=0){
            cout<<"NO"<<endl;
            flag=false;
            break;
        }
    }
    if (flag) cout<<"YES"<<endl;
    return 0;
}
-------------

B. Hopscotch

----

模拟计算(x,y)所在的格子
公式易推,注意边界

----

#include <iostream>
#include <cstring>
using namespace std;

void solve(int a,int x,int y){
    if (y%a==0){
        cout<<-1<<endl;
        return;
    }
    int fl=y/a;
    if (fl==0){
        if (2*x<a&&2*x>-a) cout<<1<<endl;
        else cout<<-1<<endl;
        return;
    }
    int nu=(fl+1)/2;
    if (fl%2==1){
        if (2*x<a&&2*x>-a) cout<<nu*3-1<<endl;
        else cout<<-1<<endl;
        return;
    }
    else{
        if (x>0&&x<a) cout<<nu*3+1<<endl;
        else if (x<0&&x>-a) cout<<nu*3<<endl;
        else cout<<-1<<endl;
        return;
    }
}

int main()
{
    int a,x,y;
    cin>>a>>x>>y;
    solve(a,x,y);
    return 0;
}

--------------

C. Queue

---

有n个人排成一队

给出每个人前面比他高的人数

构造一个身高序列

---

#include <iostream>
#include <cstring>
#include <cstdio>
#include <algorithm>
using namespace std;
const int INF=0x3f3f3f;
const int MAXN=10000;
struct Data{
    string name;
    int a;
    int h;
}f[MAXN];
bool cmp(Data x,Data y){
    return x.a<y.a;
}
int n,m;
int main()
{
    cin>>n;
    for (int i=0;i<n;i++){
        cin>>f[i].name>>f[i].a;
    }
    sort(f,f+n,cmp);
    for (int i=0;i<n;i++){
        if (f[i].a>i){
            cout<<-1<<endl;
            return 0;
        }
    }
    m=0;
    for (int i=0;i<n;i++){
        f[i].h=i+1-f[i].a;
        for (int j=0;j<i;j++){
            if (f[j].h>=f[i].h) f[j].h++;
        }

    }
    for (int i=0;i<n;i++){
        cout<<f[i].name<<" "<<f[i].h<<endl;
    }
    return 0;
}

--------------

D. Take-off Ramps

----

长度为L的场地里有n个跳板

对位于坐标Xi的跳板,要提前Pi米准备,跳到Di用时Ti。

问从0到L的最短距离。

----

以0、L、Xi-Pi、Xi+Di为顶点构造图。

从0到L的最短路即为所求。

将每个顶点按坐标排序,相邻两个顶点之间建一条长度为两点距离差绝对值的边

跳板两端点间建一条长度为Pi+Ti的边。

距离有可能超过int。

注意输出格式以及时间效率。

--------------

#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
#include <vector>
#include <map>
#include <cstdio>
using namespace std;
typedef long long LL;
const long long INF=1LL << 60;
const int maxn=500000;
const int maxm=5000000;
struct EdgeNode{
    int to;
    LL w;
    int next;
};/*==============================================*
 | Dijkstra+堆优化
 | INIT: init(n);addedge(u,v,c);节点编号0~n
 | CALL: dijkstra(int s);dis[]:最短路;pre[]:前驱
*==============================================*/
struct HeapNode{
    LL d;
    int u;
    HeapNode(){}
    HeapNode(LL a,int b):d(a),u(b){}
    bool operator<(const HeapNode& rhs) const{
        return d>rhs.d;
    }
};
struct Dijkstra{
    EdgeNode edges[maxm];
    int head[maxn];
    int edge,n;
    void init(int n){
        this->n=n;
        memset(head,-1,sizeof(head));
        edge=0;
    }
    void addedge(int u,int v,LL c){
        edges[edge].w=c,edges[edge].to=v,edges[edge].next=head[u],head[u]=edge++;
    }
    bool done[maxn];
    LL dis[maxn];
    int pre[maxn];
    void dijkstra(int s){
        priority_queue<HeapNode>que;
        for (int i=0;i<=n;i++) dis[i]=INF;
        dis[s]=0;
        memset(done,0,sizeof(done));
        que.push(HeapNode(0,s));
        while (!que.empty()){
            HeapNode x=que.top();
            que.pop();
            int u=x.u;
            if (done[u]) continue;
            done[u]=true;
            for (int i=head[u];i!=-1;i=edges[i].next){
                int v=edges[i].to;
                LL w=edges[i].w;
                if (dis[v]>dis[u]+w){
                    dis[v]=dis[u]+w;
                    pre[v]=u;
                    que.push(HeapNode(dis[v],v));
                }
            }
        }
    }
}G;
struct Data{
    int x,d,t,p;
    int id;
}a[maxn];
struct POI{
    int p;
    int id;
    POI(){}
    POI(int a,int b):p(a),id(b){}
};
vector<POI>vec;
bool cmp(POI a,POI b){
    return a.p<b.p;
}
vector<int>ans;
int mp[maxn];
int main()
{
    int n,L,m;
    memset(mp,-1,sizeof(mp));
    scanf("%d%d",&n,&L);
    G.init(2*n+1);
    m=0;
    for (int i=1;i<=n;i++){
        scanf("%d%d%d%d",&a[i].x,&a[i].d,&a[i].t,&a[i].p);
        a[i].id=i;
        G.addedge(i,i+n,a[i].p+a[i].t);
        if (a[i].t<a[i].d){
            mp[i+n]=i;
        }
        //cerr<<i<<" "<<i+n<<" "<<a[i].t<<endl;
        vec.push_back(POI(a[i].x-a[i].p,i));
        vec.push_back(POI(a[i].x+a[i].d,i+n));
    }
    vec.push_back(POI(L,2*n+1));
    vec.push_back(POI(0,0));
    sort(vec.begin(),vec.end(),cmp);
    for (int i=0;i<(int)vec.size()-1;i++){
        if (vec[i].p<0) continue;
        G.addedge(vec[i].id,vec[i+1].id,abs(vec[i+1].p-vec[i].p));
        G.addedge(vec[i+1].id,vec[i].id,abs(vec[i].p-vec[i+1].p));
        //cerr<<vec[i].id<<" "<<vec[i+1].id<<" "<<abs(vec[i+1].p-vec[i].p)<<endl;
    }
    G.dijkstra(0);
    printf("%I64d
",G.dis[2*n+1]);
    int t=2*n+1;
    while (t!=0){
        if (mp[t]==G.pre[t]) ans.push_back(G.pre[t]);
        t=G.pre[t];
    }
    printf("%d
",ans.size());
    for (int i=(int)ans.size()-1;i>=0;i--){
        printf("%d ",ans[i]);
    }
    printf("
");
    return 0;
}

-------------

E. Clearing Up

--------

有n个节点的图,求最小生成树,要求S与M各占一半。

---------

易知最小生成树有n-1条边,一半为S一半为M

定义两个并查集S1、S2。答案集e1,e2。

保证属于一个集合的顶点中,任意两个顶点之间有且只有一条简单路径。

首先只考虑S边,将S边相连的顶点合并到并查集S1里的一个集合

考虑M边,若最终想要得到一个最小生成树,则并查集S1中必须只有一个集合。

所以枚举所有M边,若某M边能连接S1中不同集合的顶点,则在S1、S2中合并这两个顶点,将该M边加入答案集e1。

如果此时M边不满(n-1)/2,枚举M边,若该边能连接S2中的不同集合则合并这两个集合并将该M边加入答案集e1。

枚举所有S边,若能连接S2中不集合则合并集合并将该S边加入答案集e2。

最终答案集e1中储存的是最小生成树中的M边,e2为S边。并且size(e1)=(n-1)/2。

若size(e1)!=size(e2)则无解。

---------

#include <iostream>
#include <vector>
#include <cstring>
#define sz(x) int(x.size())
using namespace std;
const int maxn=11111;
const int maxm=111111;
struct DisjointSet{
    int pa[maxn];
    void makeSet(int n){
        for (int i=0;i<=n;i++) pa[i]=i;
    }
    int findSet(int x){
        if (x!=pa[x]) pa[x]=findSet(pa[x]);
        return pa[x];
    }
    void unionSet(int x,int y){
        x=findSet(x);
        y=findSet(y);
        if (x!=y) pa[x]=y;
    }
}s1,s2;

int n,m;
struct Edge{
    int u,v;
    char c;
};
Edge vec[maxm];
vector<int> e1,e2;
int d;
int main()
{
    cin>>n>>m;
    for (int i=0;i<m;i++){
        cin>>vec[i].u>>vec[i].v>>vec[i].c;
    }
    s1.makeSet(n);
    s2.makeSet(n);
    for (int i=0;i<m;i++){
        if (vec[i].c=='S'){
            if (s1.findSet(vec[i].u)!=s1.findSet(vec[i].v)){
                s1.unionSet(vec[i].u,vec[i].v);
            }
        }
    }
    d=(n-1)/2;
    for (int i=0;i<m;i++){
        if (vec[i].c=='M'){
            if (s1.findSet(vec[i].u)!=s1.findSet(vec[i].v)){
                s1.unionSet(vec[i].u,vec[i].v);
                s2.unionSet(vec[i].u,vec[i].v);
                e1.push_back(i);
                d--;
            }
        }
    }
    for (int i=0;i<m;i++){
        if (vec[i].c=='M'&&d>0){
            if (s2.findSet(vec[i].u)!=s2.findSet(vec[i].v)){
                s2.unionSet(vec[i].u,vec[i].v);
                e1.push_back(i);
                d--;
            }
        }
    }
    for (int i=0;i<m;i++){
        if (vec[i].c=='S'){
            if (s2.findSet(vec[i].u)!=s2.findSet(vec[i].v)){
                s2.unionSet(vec[i].u,vec[i].v);
                e2.push_back(i);
            }
        }
    }
    d=(n-1)/2;
    if (sz(e1)!=d||sz(e2)!=d) cout<<-1<<endl;
    else{
        cout<<n-1<<endl;
        for (int i=0;i<sz(e1);i++){
            cout<<e1[i]+1<<" ";
        }
        for (int i=0;i<sz(e2);i++){
            cout<<e2[i]+1<<" ";
        }
        cout<<endl;
    }
    return 0;
}


---------

-

原文地址:https://www.cnblogs.com/cyendra/p/3681640.html