• 暑假N天乐【比赛篇】 —— 2019杭电暑期多校训练营(第六场)


    我胡汉三又滚回来了....保质期过了的题也得记下来。

    以下题解包括:

    [1002【HDU-6635】 \ 1005【HDU-6638】 \ 1006【HDU-6639】 \ 1008【HDU-6641】 \ 1012【HDU-6645】 ]

    【1002】 LIS+暴力 HDU-6635 Nonsense Time

    http://acm.hdu.edu.cn/showproblem.php?pid=6635

    参考:https://blog.csdn.net/henuyh/article/details/98845165

    给定长度为 (n) 的两个数组 (a,b)(b_i) 表示 (a) 中下标为 (b_i) 的数字当前可用,求 (b_i) 对应的 (a) 中的 LIS,(a) 中是 ([1,n]) 的全排列。

    由于数据随机生成,LIS 的期望长度为 (sqrt{n}),删除元素在 LIS 中的概率为 (frac{1}{sqrt{n}}),因此总复杂度:(o(nsqrt{n}log(n))))。先求解全部的 LIS,然后从后往前遍历数组 (b),如果删除的元素在 LIS 中就重新求一次。需要记录 LIS 的路径。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    const int maxn = 5e4+5;
    
    int n;
    int a[maxn];
    int b[maxn];
    int vis[maxn];
    int ans[maxn];
    int temp[maxn];
    int path[maxn];
    int used[maxn];
    
    int solve() {
        int len = 0;
        for(int i = 1; i <= n; i++) {
            if(vis[a[i]] == 1) {
                continue;
            }
            int x = lower_bound(temp, temp+len, a[i]) - temp;
            if(x == len) {
                temp[len++] = a[i];
                path[i] = len;
            }
            else {
                temp[x] = a[i];
                path[i] = x + 1;
            }
        }
        memset(used, 0, sizeof(used));
        int x = len;
        for(int i = n; i >= 1; i--) {
            if(vis[a[i]] == 1) {
                continue;
            }
            if(path[i] == x) {
                used[a[i]] = 1;
                x--;
            }
        }
        return len;
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            memset(vis, 0, sizeof(vis));
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                scanf("%d", &a[i]);
            }
            for(int i = 1; i <= n; i++) {
                scanf("%d", &b[i]);
            }
            ans[n] = solve();
            for(int i = n-1; i >= 1; i--) {
                vis[a[b[i+1]]] = 1;
                if(used[a[b[i+1]]] == 0) {
                    ans[i] = ans[i+1];
                }
                else {
                    ans[i] = solve();
                }
            }
            for(int i = 1; i <= n; i++) {
                printf("%d%c", ans[i], i==n?'
    ':' ');
            }
        }
        return 0;
    }
    

    【1005】 线段树 HDU-6638 Snowy Smile

    http://acm.hdu.edu.cn/showproblem.php?pid=6638

    参考:https://blog.csdn.net/A_Thinking_Reed_/article/details/98778260

    给定 (n(leq 2000)) 个点坐标和对应的权值,求最大权值和矩阵。

    每次枚举上下边界,每次向线段树中加点,维护上下边界内的最大子段和【区间最大子段和】,要注意移动上边界时可能会有多个点在当前直线上,同样的,移动下边界时要把边界上的所有点都更新后才能更新 (ans)

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    const int maxn = 2e3+5;
    
    struct node{
        int x, y;
        ll val;
        bool operator < (const node &q) const {
            if(y == q.y) {
                return x < q.x;
            }
            return y > q.y;
        }
    }p[maxn];
    
    struct NODE {
        ll sum, lsum, rsum, maxsum;
    }T[maxn << 2];
    
    int n; 
    vector<int> vx, vy;
    
    int get_xid(int x) {
        return lower_bound(vx.begin(), vx.end(), x) - vx.begin() + 1;
    }
    
    int get_yid(int y) {
        return lower_bound(vy.begin(), vy.end(), y) - vy.begin() + 1;
    }
    
    void pushup(int rt) {
        T[rt].sum = T[rt<<1].sum + T[rt<<1|1].sum;
        T[rt].lsum = max(T[rt<<1].lsum, T[rt<<1].sum + T[rt<<1|1].lsum);
        T[rt].rsum = max(T[rt<<1|1].rsum, T[rt<<1|1].sum + T[rt<<1].rsum);
        T[rt].maxsum = max(T[rt<<1].rsum+T[rt<<1|1].lsum, max(T[rt<<1].maxsum, T[rt<<1|1].maxsum));
    }
    
    void build(int l, int r, int rt) {
        T[rt].sum = T[rt].lsum = T[rt].rsum = T[rt].maxsum = 0;
        if(l == r) {
            return ;
        }
        int mid = (l+r) >> 1;
        build(l, mid, rt<<1);
        build(mid+1, r, rt<<1|1);
        pushup(rt);
    }
    
    void update(int l, int r, int pos, int val, int rt) {
        if(l == r) {
            T[rt].sum = T[rt].lsum = T[rt].rsum = T[rt].maxsum = T[rt].sum+val;
            return ;
        }
        int mid = (l+r) >> 1;
        if(pos <= mid) {
            update(l, mid, pos, val, rt<<1);
        }
        else {
            update(mid+1, r, pos, val, rt<<1|1);
        }
        pushup(rt);
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            vx.clear();
            vy.clear();
            scanf("%d", &n);
            for(int i = 1; i <= n; i++) {
                scanf("%d%d%lld", &p[i].x, &p[i].y, &p[i].val);
                vx.push_back(p[i].x);
                vy.push_back(p[i].y);
            }
            sort(vx.begin(), vx.end());
            vx.erase(unique(vx.begin(), vx.end()), vx.end());
            sort(vy.begin(), vy.end());
            vy.erase(unique(vy.begin(), vy.end()), vy.end());
            int new_n = vx.size();
            for(int i = 1; i <= n; i++) {
                p[i].x = get_xid(p[i].x);
                p[i].y = get_yid(p[i].y);
            }
            sort(p+1, p+1+n);
            ll ans = 0;
            int lst_y = -1;
            for(int i = 1; i <= n; i++) {
                if(lst_y == p[i].y) {
                    continue;
                }
                build(1, new_n, 1);
                for(int j = i; j <= n; ) {
                    int k;
                    for(k = j; k <= n && p[k].y == p[j].y; k++) {
                        update(1, new_n, p[k].x, p[k].val, 1);
                    }
                    ans = max(ans, T[1].maxsum);
                    j = k;
                }
                lst_y = p[i].y;
            }
            printf("%lld
    ", ans);
        }
        return 0;
    }
    

    【1006】 思维 HDU-6639 Faraway

    http://acm.hdu.edu.cn/showproblem.php?pid=6639

    (n) 个二维坐标点(士兵),他们有一个共同的目的地 ((x_{e},y_{e})),知道 (x_e)(y_e) 都在 ([0,m]) 的范围内,但是他们都只知道自己位置 ((x_i,y_i)) 和目标的大概情况为 ((|x_{i}-x_{e}|+|y_{i}-y_{e}|) \% k_{i} = t_{i}) 现在问你有多少个可能的目标 ((x_e,y_e))

    (|x_i - x_e| + |y_i - y_e|) 的绝对值拆掉,则每个点 ((x_i, y_i)) 会将平面分割成 4 个部分,一共 (n^2) 个区域。枚举每个区域,计算该区域中可能的终点数量。因为 (lcm(2, 3, 4, 5) = 60),所以只需要枚举 (x_e)(y_e) 模 60 的余数,(o(n)) 判断是否可行。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    int n, m;
    vector<int> vx, vy;
    
    struct node {
        int x, y;
        int k, t;
    }p[15];
    
    int check(int a, int b) {
        for(int i = 1; i <= n; i++) {
            if((abs(a-p[i].x)+abs(b-p[i].y))%p[i].k != p[i].t) {
                return 0;
            }
        }
        return 1;
    }
    
    int cal(int x, int y) {
        if(y-x-1 < 0) {
            return 0;
        }
        return ((y-x-1)/60) + 1; 
    }
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            vx.clear();
            vy.clear();
            scanf("%d%d", &n, &m);
            for(int i = 1; i <= n; i++) {
                scanf("%d%d%d%d", &p[i].x, &p[i].y, &p[i].k, &p[i].t);
                vx.push_back(p[i].x);
                vy.push_back(p[i].y);
            }
            vx.push_back(0);
            vx.push_back(m+1);
            vy.push_back(0);
            vy.push_back(m+1);
            sort(vx.begin(), vx.end());
            vx.erase(unique(vx.begin(), vx.end()), vx.end());
            int nx = vx.size();
            sort(vy.begin(), vy.end());
            vy.erase(unique(vy.begin(), vy.end()), vy.end());
            int ny = vy.size();
            ll ans = 0;
            for(int i = 0; i < nx-1; i++) {
                for(int j = 0; j < ny-1; j++) {
                    for(int k = 0; k < 60; k++) {
                        for(int l = 0; l < 60; l++) {
                            if(check(vx[i]+k, vy[j]+l)) {
                                ans += 1ll*cal(vx[i]+k, vx[i+1])*cal(vy[j]+l, vy[j+1]);
                            }
                        }
                    }
                }
            }
            printf("%lld
    ", ans);
        }   
        return 0;
    }
    

    【1008】 数学 HDU-6641 TDL

    http://acm.hdu.edu.cn/showproblem.php?pid=6641

    队友写的,就酱。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cmath>
    #define lson node<<1
    #define rson node<<1|1
    using namespace std;
    typedef long long ll;
    
    const ll inf = 2e18;
    const ll mod = 998244353;
    const int maxn = 1e5 + 20;
    
    
    ll gcd(ll a, ll b) {
        return b == 0 ? a : gcd(b, a % b);
    }
    
    
    int main() {
        int t;
        scanf("%d", &t);
        while (t--) {
            ll k, m;
            scanf("%lld%lld", &k, &m);
            ll ans = inf;
            int flag = 0;
            for (int i = 1; i <= 2000; i++) {
                ll n = k ^ i;
                int cnt = 0;
                int j = 1;
                for (; j <= 1000; j++) {
                    if (gcd(j + n, n) == 1) {
                        cnt++;
                        if (cnt == m)
                            break;
                    }
                }
                if ((n + j) == (i + n)) {
                    ans = min(ans, n);
                    flag = 1;
                }
            }
            if (flag)
                printf("%lld
    ", ans);
            else
                printf("-1
    ");
        }
    }
    

    【1012】 水题 HDU-6645 permutation 2

    http://acm.hdu.edu.cn/showproblem.php?pid=6645

    我也不知道比赛时候为什么会去写拓扑...

    就排个序一人一个分了就行。

    #include <map>
    #include <set>
    #include <list>
    #include <cmath>
    #include <ctime>
    #include <deque>
    #include <stack>
    #include <queue>
    #include <bitset>
    #include <cctype>
    #include <cstdio>
    #include <vector>
    #include <string>
    #include <cstdlib>
    #include <cstring>
    #include <fstream>
    #include <iomanip>
    #include <numeric>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const double PI = acos(-1.0);
    const double eps = 1e-6;
    const int inf = 0x3f3f3f3f;
    const int mod = 1e9 + 7;
    
    int a[100005];
    
    int main() {
        int t;
        scanf("%d", &t);
        while(t--) {
            int n;
            scanf("%d", &n);
            for(int i = 0; i < n; i++) {
                scanf("%d", &a[i]);
            }
            sort(a, a+n);
            ll ans1 = 0, ans2 = 0;
            for(int i = n-1; i >= 0; i-=2) {
                ans1 = ans1 + 1ll*a[i];
            }
            for(int i = n-2; i >= 0; i-=2) {
                ans2 = ans2 + 1ll*a[i];
            }
            printf("%lld %lld
    ", ans1, ans2);
        }
        return 0;
    }
    
  • 相关阅读:
    第八章
    第十章
    第九章
    第七章
    第六章
    第五章
    第四章心得
    第二章心得
    第三章心得
    第一章心得
  • 原文地址:https://www.cnblogs.com/Decray/p/11365864.html
Copyright © 2020-2023  润新知