2020.10.03天梯赛练习

题目:排座位

思路:

这个题直接暴力做就可以了,开个二维数组来存储每对人的状态,后面查询时再找一下数组。这里要注意的是当两个人是敌对关系时,如果有相同的敌人或者朋友是输出 “OK but...”(当时做题时没考虑有共同敌人也输出 “OK but...”,题目没读清楚)。

解题代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
using namespace std;
const long long N = 1e10 + 7;
const int maxn = 2e5 + 5;
const long long INF = 8e18;
typedef long long ll;
map<int,int>ma;
#define for0(i,n) for(int i = 0;i < n;i++)
#define for1(i,n) for(int i = 1;i <= n;i++)
int p[110][110];

int main()
{
    int n,m,x;
    cin >> n >> m >> x;
    for(int i = 0;i < m;i++){
        int a,b,c;
        cin >> a >> b >> c;
        if(a > b)
            swap(a,b);
        p[a][b] = c;
    }
    for(int i = 0;i < x;i++){
        int a,b;
        cin >> a >> b;
        if(a > b)
            swap(a,b);
        if(p[a][b] == 1){
            cout << "No problem" << endl;
        }
        if(p[a][b] == 0)
            cout << "OK" << endl;
        if(p[a][b] == -1){
                int sign = 0;
            for(int i = a+1;i <= n;i++){
                if(p[a][i]  * p[b][i]  == 1 || p[a][i] * p[i][b]  == 1 ){
                    sign = 1;
                    break;

                }

            }
            if(sign){
                cout << "OK but..." << endl;
                continue;
            }
            for(int i = 1;i < a;i++){
                if(p[i][a]  * p[b][i]  == 1 || p[i][a]  * p[i][b]  == 1 ){
                    sign = 1;
                    break;

                }
            }
            if(sign){
                cout << "OK but..." << endl;
                continue;
            }
            cout << "No way" << endl;

        }
    }



}

题目:重排链表

思路:

这个题就是一个新的链表排序规则,让你重新排。首先可以用结构体来存储结点的数据和下一个结点的地址,用结构体的下标记录该结点地址。这道题,首先会有无效结点(有一个测试点会卡这一点),所以我们可以再开个数组,来记录一开始链表中结点地址变化顺序,并记录有效结点个数(代码中的num)。通过样例输出,我们可以发现,会发现每一行结束,与下一行开始输出的地址是一样的,这样我们可以想到输出方式,首先把num这一位置的输出,后面通过循环限制输出,保证按照一前一后输出,最后再加上结束地址-1.

解题代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
using namespace std;
const long long N = 1e10 + 7;
const int maxn = 2e5 + 5;
const long long INF = 8e18;
typedef long long ll;
#define for0(i,n) for(int i = 0;i < n;i++)
#define for1(i,n) for(int i = 1;i <= n;i++)
map<string,int>ma;
struct listm{
    int date;
    int next;

}l[100010];
int order[100010];
int main()
{
    int star,n,num = 0;
    cin >> star >> n;
    for(int i = 0;i < n;i++){
        int address;
        cin >> address;
        cin >> l[address].date >> l[address].next;
    }
    while(star != -1){
        order[++num] = star;
        star = l[star].next;
    }
    printf("%05d %d ",order[num],l[ order[num] ].date);
    for(int i = 2;i <= num;i++){
        if(i % 2 == 0)
            printf("%05d\n%05d %d ",order[i/2],order[i/2],l[ order[i/2] ].date);
        else
            printf("%05d\n%05d %d ",order[num - i/2],order[num - i/2],l[ order[num - i/2] ].date);
    }
    cout << -1 << endl;
    return 0;
}

题目:分而治之

思路:

可以看到数据并不是很大,可以用数组来存一下每对城市的情况,用一个标记数组来记录是否被攻占。后面先将标记数组初始化为1,后面被攻占后改为0,最后,通过之前记录下来的成对城市,进行遍历判断一遍,看是否有成对的城市还在相连。

解题代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
using namespace std;
const long long N = 1e10 + 7;
const int maxn = 2e5 + 5;
const long long INF = 8e18;
typedef long long ll;
#define for0(i,n) for(int i = 0;i < n;i++)
#define for1(i,n) for(int i = 1;i <= n;i++)

bool citysign [10010];
int point[10010][2];

int main()
{
    int n,y;
    cin >> n >> y;
    for(int i = 0;i < y;i++){
        int a,b;
        cin >> a >> b;
        point[i][0] = a;
        point[i][1] = b;
    }

    int x;
    cin >> x;
    for(int i = 0;i < x;i++){
        for(int j = 1;j <= n;j++){ 
            citysign[j] = 1;
        }
        int num,sign = 1;
        cin >> num;
        for(int j = 0;j < num;j++){
            int city;
            cin >> city;
            citysign[city] = 0;
        }
        for(int j = 0;j < y;j++){
            if(citysign[ point[j][0] ] == 1 && citysign[ point[j][1] ] == 1){
                sign = 0;
                
                break;
            }
        }
       
        if(!sign)
            cout << "NO" << endl;
        else
            cout << "YES" << endl;
    }


    return 0;
}

 

题目:社交集群

思路:

这个题就是用到了并查集,然后用一个数组记录每个人的第一个兴趣,以便后面查询父节点,然后遍历每个人的父节点,用它当作标记数组的下标记录同兴趣人数,标记数组中有多少非0元素便有多少个集合,最后将标记数组排序,输出各个集合人数即可。

解题代码:

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <string>
#include <cstring>
#include <map>
#include <set>
using namespace std;
const long long N = 1e10 + 7;
const int maxn = 1e4 + 4;
const long long INF = 8e18;
typedef long long ll;
#define for0(i,n) for(int i = 0;i < n;i++)
#define for1(i,n) for(int i = 1;i <= n;i++)

int setfrist[maxn];
int people[maxn];
int fa[maxn];

bool cmp(int a,int b){
    return a > b;
}
int Find(int x){
    if(fa[x] == x)
        return x;
    else
        return fa[x] = Find(fa[x]);
}
void hebing(int a,int b){
    int fx = Find(a),fy = Find(b);
    if(fx != fy)
        fa[fx] = fy;
}

int main(){
    for1(i,maxn){
        fa[i] = i;
    }
    int t;
    cin >> t;
    for0(i,t){
        int m,temp;
        scanf("%d: ",&m);
        cin >> temp;
        setfrist[i] = temp;
        for(int j = 1;j < m;j++){
            int x;
            cin >> x;
            hebing(temp,x);
        }
    }
    int num = 0;
    for0(i,t){
        people[ Find(setfrist[i]) ]++;
    }
    for1(i,maxn){
        if(people[i])
            num++;
    }
    sort(people,people+maxn,cmp);
    cout << num << endl;
    for(int i = 0;i < num;i++){
        if(i != num-1)
            cout << people[i] << " ";
        else
            cout << people[i] << endl;
    }



    return 0;
}

 

posted @ 2020-10-10 11:00  emhhbw==  阅读(108)  评论(0)    收藏  举报