2020牛客多校训练第三场(待更新)

题目 完成情况
A. Clam and Fish
B. Classical String Problem
C.Operation Love
D. Points Construction Problem
E.Two Matchings
F.Fraction Construction Problem
G.Operating on a Graph
H.Sort the Strings Revision
I.Sorting the Array
J.Operating on the Tree
K.Eleven Game
L.Problem L is the Only Lovely Problem

题目:A Clam and Fish

分析:

扫一遍,对于2和3一定是拿鱼,对于1,先从当前位置往后找,找到第一个没用过的0位置,前者存诱饵,后者抓鱼。当找不到0位置的时候,剩下的所有的1位置操作分别是存诱饵、抓鱼、存诱饵、抓鱼…

代码:

#include 
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 1e9 + 7;
const int maxn = 2e6 + 10;
const int inf = 0x3f3f3f3f;
int a[maxn];

int main()
{
    int t; cin >> t;
    while(t--)
    {
        int n; cin >> n;
        int res = 0;
        for(int i = 1; i <= n; i++) scanf("%1d", a + i), res += (a[i] >= 2);
        int nex = 1;
        int flag = 0;
        for(int i = 1; i <= n; i++)
            if(a[i] == 1)
            {
                while((nex <= i || a[nex]) && nex <= n) nex++;
                if(nex == n + 1)
                {
                    int sum = 0;
                    for(int j = i; j <= n; j++) sum += (a[j] == 1);
                    res += sum / 2;
                    flag = 1;
                    break;
                }
                res++, nex++;
            }
        cout << res << endl;
    }
}

题目:D. Points Construction Problem

分析:

参考博客

代码:

#include 
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 1e9 + 7;
const int maxn = 2e6;
const int inf = 0x3f3f3f3f;
struct node
{
    int x, y;
    node(int x = 0, int y = 0) : x(x), y(y){}
};

int main()
{
    int t; cin >> t;
    while(t--)
    {
        int n, m; cin >> n >> m;
        int minn = inf;
        int x, y;
        for(int i = 1; i <= m; i++)
            for(int j = 1; j <= m; j++)
                if(n <= i * j && n > (i - 1) * j && 2 * (i + j) < minn)
                    minn = 2 * (i + j), x = i, y = j;
        if(m > 4 * n || m & 1 || m < minn)
        {
            cout << "No" << endl;
            continue;
        }
        vector<node> res1, res2;
        for(int i = 1; i <= x; i++)
            for(int j = 1; j <= y && (i - 1) * y + j <= n; j++)
                res1.push_back(node(i, j));
        int now = minn;
        int yy = y;
        x = 1000, y = 1000;
        while(res1.size() > 1 && m >= now + 4)
        {
            node u = res1.back(); res1.pop_back();
            if(u.x == 1 || u.y == 1) now += 2;
            else now += 4;
            res2.push_back(node(x, y));
            x += 2;
        }
        if(now + 2 == m)
        {
            node u = res1.back(); res1.pop_back();
            if(u.x == 1 || u.y == 1) res2.push_back(node(x, y));
            else res1.push_back(node(u.x + 1, u.y + 1));
        }
        cout << "Yes" << endl;
        for(int i = 0; i < res1.size(); i++)
            printf("%d %d\n", res1[i].x, res1[i].y);
        for(int i = 0; i < res2.size(); i++)
            printf("%d %d\n", res2[i].x, res2[i].y);
    }
}

题目:E.Two Matchings

分析:

参考博客

代码:

#include 
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 1e9 + 7;
const int maxn = 2e6;
const ll inf = 1e18;
ll a[maxn];
ll dp[maxn];

int main()
{
    int t; cin >> t;
    while(t--)
    {
        int n; cin >> n;
        for(int i = 1; i <= n; i++) cin >> a[i];
        sort(a + 1, a + 1 + n);
        ll res = 0;
        for(int i = 2; i <= n; i += 2)
            res += a[i] - a[i - 1];
        dp[2] = inf;
        dp[4] = a[4] - a[1] + a[3] - a[2];
        dp[6] = a[6] - a[1] + a[5] - a[4] + a[3] - a[2];
        for(int i = 8; i <= n; i += 2)
            dp[i] = min(dp[i - 4] + a[i] - a[i - 3] + a[i - 1] - a[i - 2], dp[i - 6] + a[i] - a[i - 5] + a[i - 1] - a[i - 2] + a[i - 3] - a[i - 4]);
        cout << res + dp[n] << endl;
    }
}

F.Fraction Construction Problem

分析:

参考博客

代码:

#include 
using namespace std;

typedef long long ll;
const int mac=2e6+10;

int min_prim[mac],prim_num[mac];
int vis[mac];

void init()
{
    int m=sqrt(mac);
    for (int i=2; i<m; i++){
        if (!vis[i]){
            min_prim[i]=i;
            for (int j=i*i; j<mac; j+=i){
                vis[j]=1;
                if (!min_prim[j]) min_prim[j]=i;//找到每个数的最小质因子
            }
        }
    }
    for (int i=1; i<mac; i++){
        if (!vis[i]) continue;
        prim_num[i]++;
        int x=i;
        while (x%min_prim[i]==0) x/=min_prim[i];
        if (x!=1) prim_num[i]++;//判断是否有两个互异的质因子 
    }
}

ll exgcd(ll a,ll b,ll &x,ll &y)
{
    if (!b) {
        x=1; y=0;
        return a;
    }
    ll d=exgcd(b,a%b,y,x);
    y-=a/b*x;
    return d;
}

int main(int argc, char const *argv[])
{
    int t;
    init();
    scanf ("%d",&t);
    while (t--){
        int a,b;
        scanf ("%d%d",&a,&b);
        int g=__gcd(a,b);
        if (g!=1) {
            printf("%d %d %d %d\n",a/g+1,b/g,1,b/g);
            continue;
        }
        if (prim_num[b]<=1) {printf("-1 -1 -1 -1\n"); continue;}
        ll d=1,f=b;
        while (f%min_prim[b]==0) {
            f/=min_prim[b];
            d*=min_prim[b];
        }
        ll c,e;
        exgcd(f,d,c,e);
        e=-e;
        while (e<0 || c<0) e+=f,c+=d;
        printf ("%lld %lld %lld %lld\n",1LL*c*a,d,1LL*e*a,f);
    }
    return 0;
}

题目:G.Operating on a Graph

分析:

每个group看做一个并查集,用容器存储每个group的相邻的点,每次扫描与group u相邻的点v,合并group u和group find(v)

代码:

#include 
using namespace std;
typedef long long ll;
//typedef __int128 lll;
#define print(i) cout << "debug: " << i << endl
#define close() ios::sync_with_stdio(0), cin.tie(0), cout.tie(0)
#define mem(a, b) memset(a, b, sizeof(a))
const ll mod = 1e9 + 7;
const int maxn = 2e6;
const int inf = 0x3f3f3f3f;
set<int> g[maxn];
int fa[maxn];

int find(int x)
{
    return fa[x] = x == fa[x] ? x : find(fa[x]);
}

void merge(set<int> &a, set<int> &b)
{
    if(a.size() < b.size()) swap(a, b);
    for(int it : b) a.insert(it);
}

int main()
{
    int t; cin >> t;
    while(t--)
    {
        int n, m; cin >> n >> m;

        for(int i = 0; i < n; i++) fa[i] = i, g[i].clear();
        for(int i = 1; i <= m; i++)
        {
            int x, y; cin >> x >> y;
            g[x].insert(y), g[y].insert(x);
        }
        int q; cin >> q;
        while(q--)
        {
            int x; cin >> x;
            if(find(x) != x) continue;
            set<int> now = g[x];
            g[x].clear();
            for(int it : now)
            {
                int f = find(it);
                if(f == x) continue;
                fa[f] = x;
                merge(g[x], g[f]);
            }
        }
        for(int i = 0; i < n; i++)
            printf("%d%c", find(i), i == n - 1 ? '\n' : ' ');
    }
}

你可能感兴趣的:(牛客多校)