• 衡八联考2



    线下评测文件名写的abc,连续第3天爆0了

    A 最长公共子序列

    题目大意 : 求4个序列的最长公共子序列,保证前3个序列每个序列不会有数字出现次数大于2

    • n4的dp很好些,f[i][j][k][l]表示a,b,c,d分别考虑到前i,j,k,l个,最长公共子序列的长度

    • 发现a[i]=b[j]=c[k]=d[l]的情况不多,所以有效转移只有8n个,转移是是从i,j,k,l都小的地方转移

    • 于是就是一个4维偏序优化的dp,可用CDQ+二维树状数组通过

    Code

    Show Code
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    
    using namespace std;
    const int N = 1e4 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, p1[N][3], p2[N][3], p3[N][3], f[N*8], cnt, t[N][N], ans;
    
    struct Node {
        int a, b, c, d, id;
    }a[N*8], g[N*8];
    
    bool operator < (const Node &x, const Node &y) {
        return x.a != y.a ? x.a < y.a : x.id < y.id;
    }
    
    void Add(int x, int y, int w) {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= n; j += j & -j)
                t[i][j] = max(t[i][j], w);
    }
    
    int Ask(int x, int y, int ans = 0) {
        for (int i = x; i; i -= i & -i)
            for (int j = y; j; j -= j & -j)
                ans = max(ans, t[i][j]);
        return ans;
    }
    
    void Clear(int x, int y) {
        for (int i = x; i <= n; i += i & -i)
            for (int j = y; j <= n && t[i][j]; j += j & -j)
                t[i][j] = 0;
    }
    
    void Solve(int l, int r) {
        if (a[l].d == a[r].d) return;
        int mid = l + r >> 1;
        while (a[mid].d == a[l].d) mid++; mid--;
        while (a[mid].d == a[mid+1].d) mid--;
        Solve(l, mid); 
        memcpy(g + l, a + l, sizeof(Node) * (r - l + 1));
        sort(g + l, g + mid + 1); sort(g + mid + 1, g + r + 1);
        int i = l, j = mid + 1;
        for (; j <= r; ++j) {
            for (; i <= mid && g[i].a < g[j].a; ++i)
                Add(g[i].b, g[i].c, f[g[i].id]);
            f[g[j].id] = max(f[g[j].id], Ask(g[j].b - 1, g[j].c - 1) + 1);
        }
        for (--i; i >= l; --i) Clear(g[i].b, g[i].c);
        Solve(mid + 1, r);
    }
    
    int main() {
        freopen("lcs.in", "r", stdin);
        freopen("lcs.out", "w", stdout);
        n = read();
        for (int i = 1, x; i <= n; ++i) x = read(), (!p1[x][0] ? p1[x][0] : p1[x][1]) = i;
        for (int i = 1, x; i <= n; ++i) x = read(), (!p2[x][0] ? p2[x][0] : p2[x][1]) = i;
        for (int i = 1, x; i <= n; ++i) x = read(), (!p3[x][0] ? p3[x][0] : p3[x][1]) = i;
        for (int i = 1; i <= n; ++i) {
            int x = read();
            for (int j = 0; p1[x][j]; ++j)
                for (int k = 0; p2[x][k]; ++k)
                    for (int l = 0; p3[x][l]; ++l)
                        a[++cnt] = (Node) {p1[x][j], p2[x][k], p3[x][l], i, cnt}, f[cnt] = 1;
        }
        Solve(1, cnt);
        for (int i = 1; i <= cnt; ++i)
            ans = max(ans, f[i]);
        printf("%d
    ", ans);
        return 0;
    }
    

    B 排列

    题目大意 : 求一个字典序最小的排列使得相邻位置值的异或值的最大值最小

    • 求出最小值和一组字典序不一定最小的方案好求

    • 从最高位开始考虑,如果每个数在这位都一样,那相邻异或值在这一位一定都是0,对于第一次出现不一样的位,答案一定不会小于这一位的值

    • 而答案其实就是这一位为0的数与这一位为1的数的异或值的最小值,

    • 然后就可以考虑每个位置可以放什么了

    Code

    Show Code
    #include <set>
    #include <map>
    #include <cstdio>
    #include <algorithm>
    
    using namespace std;
    const int N = 3e5 + 5;
    
    int read(int x = 0, int f = 1, char c = getchar()) {
        for (; c < '0' || c > '9'; c = getchar()) if (c == '-') f = -1;
        for (; c >='0' && c <='9'; c = getchar()) x = x * 10 + c - '0';
        return x * f;
    }
    
    int n, a[N], cnt, sum, m, s[N], ans = 1e9, ch[N*30][2], trc, c[2], tot, lt, t[N];
    set<int> b[2], p[N];
    map<int, int> mp;
    
    void Insert(int x) {
        int p = 0;
        for (int i = 29; i >= 0; --i) {
            bool k = x & 1 << i;
            if (!ch[p][k]) ch[p][k] = ++trc;
            p = ch[p][k];
        }
    }
    
    int Ask(int x) {
        int p = 0, ans = 0;
        for (int i = 29; i >= 0; --i) {
            bool k = x & 1 << i;
            if (ch[p][k]) p = ch[p][k];
            else p = ch[p][k^1], ans += 1 << i;
        }
        return ans;
    }
    
    bool Judge(int i) {
        int x = a[i]; bool k = x & m;
        s[mp[x]]--; c[k]--; tot -= s[mp[x^ans]];
        if (tot || !c[k] || !c[k^1]) {
            p[mp[x]].erase(i); b[k].erase(i);
            printf("%d ", i); lt = x; return 1;
        }
        s[mp[x]]++; c[k]++; tot += s[mp[x^ans]];
        return 0;
    }
    
    int main() {
        freopen("permutation.in", "r", stdin);
        freopen("permutation.out", "w", stdout);
        n = read(); sum = (1 << 30) - 1;
        for (int i = 1; i <= n; ++i)
            a[i] = read(), sum &= a[i];
        for (int i = 1; i <= n; ++i) {
            a[i] ^= sum; m = max(m, a[i]);
            if (!mp[a[i]]) mp[a[i]] = ++cnt;
            s[mp[a[i]]]++;
        }
        for (; m > (m & -m); m -= m & -m);
        for (int i = 1; i <= n; ++i)
            if (a[i] & m) Insert(a[i]);
        for (int i = 1; i <= n; ++i)
            if (!(a[i] & m)) ans = min(ans, Ask(a[i]));
        for (int i = 1; i <= n; ++i) {
            bool k = a[i] & m; 
            p[mp[a[i]]].insert(i); 
            b[k].insert(i); c[k]++;
            if (k) tot += s[mp[a[i]^ans]];
        }
        for (int i = 1; i <= n; ++i)
            if (Judge(i)) break;
        for (int i = 2; i <= n; ++i) {
            int cnt = 0; bool k = lt & m;
            if (s[mp[lt^ans]]) t[++cnt] = *p[mp[lt^ans]].begin();
            if (!b[k].empty()) t[++cnt] = *b[k].begin();
            if (b[k].size() > 1) t[++cnt] = *++b[k].begin();
            sort(t + 1, t + cnt + 1);
            for (int j = 1; j <= cnt; ++j)
                if (Judge(t[j])) break;
        }
        return 0;
    }
    

    C 加农炮 (Unaccepted)

    题目大意 :

    Code

    Show Code
  • 相关阅读:
    数据库分表分库
    rabbitMq 集群
    马哥博客作业第七周
    马哥博客作业第六周
    马哥博客作业第一阶段考试
    马哥博客作业第四周
    马哥博客作业第三周
    马哥博客作业第二周
    马哥博客作业第一周
    03-MySQL数据库表的基本操作
  • 原文地址:https://www.cnblogs.com/shawk/p/14577478.html
Copyright © 2020-2023  润新知