• uestc summer training #2


    A

    增广

    #include<bits/stdc++.h>
    using namespace std;
    const int MAXN = 1000000 + 10;
    vector<int> g[MAXN];
    int a[MAXN], b[MAXN], sz[MAXN], cnt[MAXN];
    bool mg[MAXN], vis[MAXN];
    int n, m;
    bool dfs(int u, int f = -1)
    {
            if (g[u].empty())  //如果当前数没有位置是成对的(a[i+1]=a[i]+1)当然不可能缝
            {
                    return false;
            }
            //第一种情况 
            for (auto &p : g[u])  //枚举当前数每个成对的位置
                    if (p != f)
                    {
                            if (!vis[p + 1] || cnt[u + 1] == 1) //如果当前这对后面的位置没有被缝并且后面的数数量为1
                            {
                                    mg[p] = vis[p] = vis[p + 1] = 1;  //缝起来 返回true
                                    if (f != -1)
                                    {
                                            mg[f] = 0;
                                    }
                                    return true;
                            }
                    }
            for (auto &p : g[u])
                    if (p != f)
                    {
                            if (dfs(u + 1, p + 1))
                            {
                                    mg[p] = vis[p] = vis[p + 1] = 1;
                                    if (f != -1)
                                    {
                                            mg[f] = 0;
                                    }
                                    return true;
                            }
                    }
            return false;
    }
    int main()
    {
            scanf("%d", &n);
            m = 0; //m是当前数组的数量
            for (int i = 0, p(-1); i < n; ++ i)
            {
                    int x;
                    scanf("%d", &x);
                    if (x == p)  //p是上一个加入的数
                    {
                            sz[m - 1] ++; //如果现在加入的和上一个相同就给上一个sz++
                    }
                    else            //不同的话 加入当前数更新p
                    {
                            p = x;
                            a[m] = x;
                            sz[m ++] = 1;
                    }
            }
            n = m;
            for (int i = 0; i < n; i++)
            {
                    b[i] = a[i];
            }
            sort(b, b + n);
            for (int i = m = 0; i < n; i++)  //初始化m进行离散化操作
                    if (i == 0 || b[i] > b[m - 1])
                    {
                            b[m++] = b[i];
                    }
            for (int i = 0; i < n; ++ i)  //离散化
            {
                    a[i] = lower_bound(b, b + m, a[i]) - b;
                    cnt[a[i]] ++;  //计数 计算每种数的数量
            }
            //        for (int i = 0; i < n; i++)
            //        {
            //                cout << a[i] << " ";
            //        }
            //        cout << endl;
            for (int i = 0; i + 1 < n; ++ i)
            {
                    if (a[i] + 1 == a[i + 1]) //如果后一个是前一个+1就建一条有向边
                    {
                            g[a[i]].push_back(i);  //记录每一对可以缝的位置前面的哪个
                    }
            }
            int ret = n - 1; //答案(缩点之后缝之前的答案 这里claris姐姐写错了 应该是n-1)
            for (int i = m - 1; i >= 0; -- i) //从大到小尝试是否可以缝当前的数
            {
                    if (dfs(i))  //如果返回true即可以缝的话 答案减少一个
                    {
                            -- ret; //对于每一种数 最多只能缝一次 所以最多-1
                    }
            }
            printf("%d", ret);
    }
    View Code

    B

    签到题

    D

    模拟题

    F

    给你一个中序遍历 和每个点的权值 问你存不存在一颗树使得每个节点的祖先和它的权值是互质的

    解:

    质因数分解+分治模拟

    因为中序遍历有个特点 如果一个点是一个子树的根的话 左儿子都在左边 右儿子都在右边

    所以要求互质的是一段区间 用GCD来做的话肯定会超时 我们给每个合数一个leftprime表示该合数质因数分解后最小的质数

    首先我们从左到右枚举 维护每个质数所到的最右边 更新每个合数的答案 再反过来从右到左做一次

    然后模拟树分治找到根递归地看能不能构造树

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double eps = 1e-8;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int MAXN = 1e6 + 5, MAXM = 1e5 + 5;
    const int MAXQ = 100010;
    //int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
    /*inline void addedge(int u, int v, ll c)
    {
            to[++tot] = v;
            nxt[tot] = Head[u];
            cost[tot] = c;
            Head[u] = tot;
    }*/
    inline void read(int &v)
    {
            v = 0;
            char c = 0;
            int p = 1;
            while (c < '0' || c > '9')
            {
                    if (c == '-')
                    {
                            p = -1;
                    }
                    c = getchar();
            }
            while (c >= '0' && c <= '9')
            {
                    v = (v << 3) + (v << 1) + c - '0';
                    c = getchar();
            }
            v *= p;
    }
    const int N = 10000000 + 5;
    int MAXX = -1;
    bool flagsum;
    int ptot = 0;
    int num[N];
    int father[N];
    int prime[N];
    bool check[N];
    int fanwei[N];
    int leftprime[N];
    int lans[N], rans[N];
    void Euler()
    {
            ll now;
            for (int i = 2; i <= MAXX; i ++)
            {
                    if (!check[i])
                    {
                            prime[ptot ++] = i;
                    }
                    for (int j = 0; j < ptot; j ++)
                    {
                            now = 1LL * prime[j] * i;
                            if (now > MAXX)
                            {
                                    break;
                            }
                            check[now] = 1;
                            leftprime[now] = prime[j];
                            if (i % prime[j] == 0)
                            {
                                    break;
                            }
                    }
            }
    }
    bool get_ans(int fa, int l, int r)
    {
            int flag = 0;
            if (l > r)
            {
                    return true;
            }
            int aim;
            int len = (r - l - 1) / 2 + ((r - l - 1) & 1);
            for (int i = 0; i <= len; i++)
            {
                    aim = l + i;
                    if (lans[aim] < l && rans[aim] > r)
                    {
                            //cout << fa << " " << l << " " << r << " " << i << endl;
                            //cout << lans[i] << " " << rans[i] << endl;
                            flag = 1;
                            flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r);
                            if (flag)
                            {
                                    father[aim] = fa;
                                    return true;
                            }
                            else
                            {
                                    return false;
                            }
                    }
                    aim = r - i;
                    if (lans[aim] < l && rans[aim] > r)
                    {
                            //cout << fa << " " << l << " " << r << " " << i << endl;
                            //cout << lans[i] << " " << rans[i] << endl;
                            flag = 1;
                            flag = flag && get_ans(aim, l, aim - 1) && get_ans(aim, aim + 1, r);
                            if (flag)
                            {
                                    father[aim] = fa;
                                    return true;
                            }
                            else
                            {
                                    return false;
                            }
                    }
            }
            return false;
    }
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
    
            int n;
            int cnt;
            read(n);
            for (int i = 1; i <= n; i++)
            {
                    read(num[i]);
                    MAXX = max(MAXX, num[i]);
            }
            Euler();
            //        for (int i = 1; i <= 20; i++)
            //        {
            //                cout << i << " " << leftprime[i] << endl;
            //        }
            for (int i = 1; i <= n; i++)
            {
                    rans[i] = n + 1;
            }
            for (int i = 1; i <= n; i++)
            {
                    cnt = num[i];
                    if (cnt == 1)
                    {
                            continue;
                    }
                    //cout<<i<<"   ";
                    if (check[cnt] == 0)
                    {
                            //cout << "l "<<cnt << endl;
                            lans[i] = max(fanwei[cnt], lans[i]);
                            fanwei[cnt] = i;
                            continue;
                    }
                    while (check[cnt])
                    {
                            //cout << "l " << cnt << endl;
                            int primenow = leftprime[cnt];
                            lans[i] = max(fanwei[primenow], lans[i]);
                            fanwei[primenow] = i;
                            while (cnt % primenow == 0)
                            {
                                    cnt /= primenow;
                            }
                    }
                    if (cnt == 1)
                    {
                            continue;
                    }
                    else
                    {
                            //cout << "l " << cnt << endl;
                            lans[i] = max(fanwei[cnt], lans[i]);
                            fanwei[cnt] = i;
                    }
            }
            for (int i = 1; i <= N; i++)
            {
                    fanwei[i] = n + 1;
            }
            for (int i = n; i >= 1; i--)
            {
                    cnt = num[i];
                    if (cnt == 1)
                    {
                            continue;
                    }
                    //cout<<i<<"   ";
                    if (check[cnt] == 0)
                    {
                            //cout << "r "<<cnt << endl;
                            rans[i] = min(fanwei[cnt], rans[i]);
                            fanwei[cnt] = i;
                            continue;
                    }
                    while (check[cnt])
                    {
                            //cout << "r "<<cnt << endl;
                            int primenow = leftprime[cnt];
                            rans[i] = min(fanwei[primenow], rans[i]);
                            fanwei[primenow] = i;
                            while (cnt % primenow == 0)
                            {
                                    cnt /= primenow;
                            }
                    }
                    if (cnt == 1)
                    {
                            continue;
                    }
                    else
                    {
                            //                        cout << "r "<<cnt << endl;
                            //                        cout << cnt << endl;
                            rans[i] = min(fanwei[cnt], rans[i]);
                            fanwei[cnt] = i;
                    }
            }
            //                for(int i=1;i<=n;i++)
            //                {
            //                        cout<<i<<" "<<lans[i]<<" "<<rans[i]<<endl;
            //                }
            flagsum = get_ans(0, 1, n);
            if (!flagsum)
            {
                    cout << "impossible" << endl;
            }
            else
            {
                    for (int i = 1; i <= n; i++)
                    {
                            cout << father[i];
                            if (i != n)
                            {
                                    cout << " ";
                            }
                    }
                    cout << endl;
            }
            return 0;
    }
    View Code

    G

    几何题

    H

    小的直接暴力 大的加给大的

    I

    背包DP  记录路径还需要一个二维数组

    /*Huyyt*/
    #include<bits/stdc++.h>
    #define mem(a,b) memset(a,b,sizeof(a))
    using namespace std;
    typedef pair<int, int> PINT;
    typedef long long ll;
    typedef unsigned long long ull;
    const double eps = 1e-8;
    const int dir[8][2] = {{0, 1}, {1, 0}, {0, -1}, { -1, 0}, {1, 1}, {1, -1}, { -1, -1}, { -1, 1}};
    const int mod = 1e9 + 7, gakki = 5 + 2 + 1 + 19880611 + 1e9;
    const int MAXN = 1e6 + 5, MAXM = 1e5 + 5;
    const int MAXQ = 100010, INF = 1e9;
    //int to[MAXM << 1], nxt[MAXM << 1], Head[MAXN], tot = 1;
    /*inline void addedge(int u, int v, ll c)
    {
            to[++tot] = v;
            nxt[tot] = Head[u];
            cost[tot] = c;
            Head[u] = tot;
    }*/
    inline void read(int &v)
    {
            v = 0;
            char c = 0;
            int p = 1;
            while (c < '0' || c > '9')
            {
                    if (c == '-')
                    {
                            p = -1;
                    }
                    c = getchar();
            }
            while (c >= '0' && c <= '9')
            {
                    v = (v << 3) + (v << 1) + c - '0';
                    c = getchar();
            }
            v *= p;
    }
    struct node
    {
            int first, second, index;
    } bag[505];
    bool cmp(node a, node b)
    {
            return (a.first - a.second) > (b.first - b.second);
    }
    int dp[505][10005];
    int print[505][10005];
    PINT before[505][10005];
    stack<int> anser;
    int main()
    {
            ios_base::sync_with_stdio(0);
            cin.tie(0);
    
            int n, c;
            scanf("%d %d", &n, &c);
            for (int i = 1; i <= n; i++)
            {
                    scanf("%d %d", &bag[i].first, &bag[i].second);
                    bag[i].index = i;
            }
            sort(bag + 1, bag + 1 + n, cmp);
            int ans = 0;
            for (int i = 1; i <= n; i++)
                    for (int j = 0; j <= c; j++)
                    {
                            dp[i][j] = -INF;
                    }
            dp[0][0] = 0;
            PINT ed = make_pair(0, 0);
            for (int i = 1; i <= n; i++)
            {
                    for (int j = 0; j <= c; j++)
                    {
                            if (dp[i - 1][j] > dp[i][j])
                            {
                                    dp[i][j] = dp[i - 1][j];
                                    before[i][j] = make_pair(i - 1, j);
                                    print[i][j] = print[i - 1][j];
                            }
                    }
                    for (int j = 1; j <= c; j++)
                    {
                            if (j >= bag[i].second && j + bag[i].first - bag[i].second <= c)
                            {
                                    if (dp[i - 1][j - bag[i].second] != -INF)
                                    {
                                            if (dp[i][j] < dp[i - 1][j - bag[i].second] + 1)
                                            {
                                                    dp[i][j] = dp[i - 1][j - bag[i].second] + 1;
                                                    print[i][j] = bag[i].index;
                                                    before[i][j] = make_pair(i - 1, j - bag[i].second);
                                                    if (dp[i][j] > ans)
                                                    {
                                                            ans = dp[i][j];
                                                            ed = make_pair(i, j);
                                                    }
                                            }
                                    }
                            }
                    }
            }
            int printnow;
            cout << ans << endl;
            for (; ed.first; ed = before[ed.first][ed.second])
            {
                    if (printnow != print[ed.first][ed.second] && print[ed.first][ed.second] != 0)
                    {
                            anser.push(print[ed.first][ed.second]);
                    }
                    printnow = print[ed.first][ed.second];
            }
            while (!anser.empty())
            {
                    cout << anser.top() << " ";
                    anser.pop();
            }
            return 0;
    }
    View Code

    J

    找规律题

    我们可以通过打暴力程序对比发现每个2一轮一轮地模拟和一个一个地模拟得到的结果是一样的

    但是直接把一个一个滚的模拟交上去会T7 需要再简化一下 

    每当遇到一个二 找到它左边最近的0和右边最近的0位置分别为L与R

    则这一段数列除了L+R-i这个位置变成0 其他位置都会变成1

    K

    概率题

  • 相关阅读:
    【尺取】HDU Problem Killer
    【尺取或dp】codeforces C. An impassioned circulation of affection
    【搜索】codeforces C. The Tag Game
    【数学】codeforces B. The Golden Age
    【dfs+理解题意+构造】【待重做】codeforces E. Ice cream coloring
    【贪心】codeforces D. Minimum number of steps
    【数学】codeforces A. Success Rate
    【二分+交互】codeforces B. Glad to see you!
    【组合 数学】codeforces C. Do you want a date?
    JavaScript实现快速排序
  • 原文地址:https://www.cnblogs.com/Aragaki/p/9325999.html
Copyright © 2020-2023  润新知