zoukankan      html  css  js  c++  java
  • 2018冬令营模拟测试赛(十九)

    2018冬令营模拟测试赛(十九)

    [Problem A]小Y

    试题描述

    QAQ

    TAT

    输入

    见“试题描述

    输出

    见“试题描述

    输入示例

    见“试题描述

    输出示例

    见“试题描述

    数据规模及约定

    见“试题描述

    题解

    目前未知。

    这题目前就能做到 (O(n sqrt{M} log n)),其中 (M) 是逆序对数,然而会被卡 T;当然这题暴力可以拿到和左边那个算法一样的分数,只要暴力加一个剪枝:当左区间最大值小于右区间最小值时就直接输出阶乘。

    // 略(不要打我 TAT)
    

    [Problem B]暗牧

    试题描述

    T_T

    QwQ

    ToT

    输入

    见“试题描述

    输出

    见“试题描述

    输入示例

    见“试题描述

    输出示例

    见“试题描述

    数据规模及约定

    见“试题描述

    题解

    这题要用到的节点不多,自然想到构建虚树。把所有边和询问所提到的点都作为关键点,每棵树分别处理,这样能把点数压成 (4(m+q)),边数也是这个级别的,最后跑 (q) 遍最短路就好了。

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <cassert>
    using namespace std;
    #define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
    #define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
     
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
     
    #define maxtrn 300010
    #define maxlog 19
    #define maxom 100010
    #define maxn 400050
    #define maxm 1000090
    #define ool (1ll << 60)
    #define LL long long
    #define pii pair <int, int>
    #define x first
    #define y second
    #define mp(x, y) make_pair(x, y)
     
    int ToT;
    struct Graph {
        int m, head[maxn], nxt[maxm], to[maxm], dist[maxm];
     
        void AddEdge(int a, int b) {
            to[++m] = b; nxt[m] = head[a]; head[a] = m;
            swap(a, b);
            to[++m] = b; nxt[m] = head[a]; head[a] = m;
            return ;
        }
         
        void AddEdge(int a, int b, int c) {
            assert(a >= 0 && b >= 0);
            // printf("edge %d %d, %d
    ", a, b, c);
            to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
            swap(a, b);
            to[++m] = b; dist[m] = c; nxt[m] = head[a]; head[a] = m;
            return ;
        }
    } tr, G;
     
    int fa[maxtrn][maxlog], dep[maxtrn], dfn[maxtrn], clo;
    void build(int u) {
        dfn[u] = ++clo;
        rep(i, 1, maxlog - 1) fa[u][i] = fa[fa[u][i-1]][i-1];
        for(int e = tr.head[u]; e; e = tr.nxt[e]) if(tr.to[e] != fa[u][0]) {
            fa[tr.to[e]][0] = u;
            dep[tr.to[e]] = dep[u] + 1;
            build(tr.to[e]);
        }
        return ;
    }
    int lca(int a, int b) {
        if(dep[a] < dep[b]) swap(a, b);
        dwn(i, maxlog - 1, 0) if(dep[a] - dep[b] >= (1 << i)) a = fa[a][i];
        dwn(i, maxlog - 1, 0) if(fa[a][i] != fa[b][i]) a = fa[a][i], b = fa[b][i];
        return a == b ? a : fa[b][0];
    }
     
    struct Edge {
        int p1, u1, p2, u2;
        Edge() {}
        Edge(int _1, int _2, int _3, int _4): p1(_1), u1(_2), p2(_3), u2(_4) {}
    } es[maxom], qs[15];
    int num[(maxom<<1)+20], cntn, gnode[maxtrn<<1];
    vector <int> vnode[(maxom<<1)+20];
    const bool cmp(const int& a, const int& b) {
        return dfn[a] < dfn[b];
    }
    const bool cmpequ(const int& a, const int& b) {
        return dfn[a] == dfn[b];
    }
     
    const int HMOD = 1000037;
    struct Hash {
        int tot, head[HMOD], nxt[maxn], id[maxn];
        pii key[maxn];
        void Insert(pii a, int v) {
            // printf("insert: pair(%d, %d) %d
    ", a.x, a.y, v);
            int u = (a.x * 233 + a.y) % HMOD;
            nxt[++tot] = head[u]; id[tot] = v; key[tot] = a; head[u] = tot;
            return ;
        }
        int Find(pii a) {
            int u = (a.x * 233 + a.y) % HMOD;
            for(int e = head[u]; e; e = nxt[e]) if(key[e].x == a.x && key[e].y == a.y) return id[e];
            return -1;
        }
    } hh;
     
    struct Node {
        int u; LL d;
        Node() {}
        Node(int _, LL __): u(_), d(__) {}
        bool operator < (const Node& t) const { return d > t.d; }
    };
    LL d[maxn];
    bool vis[maxn];
    priority_queue <Node> Q;
    LL ShortPath(int s, int t) {
        rep(i, 1, ToT) d[i] = ool;
        memset(vis, 0, sizeof(vis));
        d[s] = 0;
        Q.push(Node(s, 0));
        while(!Q.empty()) {
            int u = Q.top().u; Q.pop();
            if(vis[u]) continue;
            vis[u] = 1;
            for(int e = G.head[u]; e; e = G.nxt[e]) if(d[G.to[e]] > d[u] + G.dist[e]) {
                d[G.to[e]] = d[u] + G.dist[e];
                if(!vis[G.to[e]]) Q.push(Node(G.to[e], d[G.to[e]]));
            }
        }
        return d[t];
    }
     
    int main() {
        int n = read(), m = read(), q = read();
        rep(i, 1, n - 1) {
            int a = read(), b = read();
            tr.AddEdge(a, b);
        }
        build(1);
        rep(i, 1, m) {
            int p1 = read(), u1 = read(), p2 = read(), u2 = read();
            es[i] = Edge(p1, u1, p2, u2);
            num[++cntn] = u1; num[++cntn] = u2;
        }
        rep(i, 1, q) {
            int p1 = read(), u1 = read(), p2 = read(), u2 = read();
            qs[i] = Edge(p1, u1, p2, u2);
            num[++cntn] = u1; num[++cntn] = u2;
        }
        sort(num + 1, num + cntn + 1);
        cntn = unique(num + 1, num + cntn + 1) - num - 1;
         
        rep(i, 1, m) {
            es[i].u1 = lower_bound(num + 1, num + cntn + 1, es[i].u1) - num;
            es[i].u2 = lower_bound(num + 1, num + cntn + 1, es[i].u2) - num;
            // printf("%d <- %d; %d <- %d
    ", es[i].u1, es[i].p1, es[i].u2, es[i].p2);
            vnode[es[i].u1].push_back(es[i].p1);
            vnode[es[i].u2].push_back(es[i].p2);
        }
        rep(i, 1, q) {
            qs[i].u1 = lower_bound(num + 1, num + cntn + 1, qs[i].u1) - num;
            qs[i].u2 = lower_bound(num + 1, num + cntn + 1, qs[i].u2) - num;
            // printf("%d <- %d; %d <- %d
    ", qs[i].u1, qs[i].p1, qs[i].u2, qs[i].p2);
            vnode[qs[i].u1].push_back(qs[i].p1);
            vnode[qs[i].u2].push_back(qs[i].p2);
        }
        rep(i, 1, cntn) {
            sort(vnode[i].begin(), vnode[i].end(), cmp);
            vector <int> :: iterator it = unique(vnode[i].begin(), vnode[i].end(), cmpequ);
            vnode[i].erase(it, vnode[i].end());
             
            // printf("tree %d:", i); for(auto j : vnode[i]) printf(" %d", j); putchar('
    ');
             
            int cntg = 0;
            rep(j, 0, vnode[i].size() - 1) {
                gnode[++cntg] = vnode[i][j];
                if(j < vnode[i].size() - 1) gnode[++cntg] = lca(vnode[i][j], vnode[i][j+1]);
            }
            sort(gnode + 1, gnode + cntg + 1, cmp);
            cntg = unique(gnode + 1, gnode + cntg + 1, cmpequ) - gnode - 1;
            rep(j, 1, cntg) hh.Insert(mp(i, gnode[j]), ++ToT);
            rep(j, 1, cntg)
                if(j > 1) {
                    int a = lca(gnode[j-1], gnode[j]);
                    G.AddEdge(hh.Find(mp(i, a)), hh.Find(mp(i, gnode[j])), dep[gnode[j]] - dep[a]);
                }
        }
        rep(i, 1, m) G.AddEdge(hh.Find(mp(es[i].u1, es[i].p1)), hh.Find(mp(es[i].u2, es[i].p2)), 1);
         
        rep(i, 1, q) {
            int p1 = qs[i].p1, u1 = qs[i].u1, p2 = qs[i].p2, u2 = qs[i].u2;
            LL ans = ShortPath(hh.Find(mp(u1, p1)), hh.Find(mp(u2, p2)));
            if(ans < ool) printf("%lld
    ", ans); else puts("impossible");
        }
         
        return 0;
    }
    

    [Problem C]大根

    试题描述

    TwT

    Q_Q

    输入

    见“试题描述

    输出

    见“试题描述

    输入示例

    见“试题描述

    输出示例

    见“试题描述

    数据规模及约定

    见“试题描述

    题解

    这题可以转化成生成 (k) 个不相交区间,要求每个元区间都包含至少一个生成的区间,且生成的区间至少被一个原区间包含。

    于是变成两种贪心取最优:

    • 将包含别的区间的区间放到集合 (B) 中,否则放到集合 (A) 中,然后枚举 (A) 中分 (k_1) 类,那么 (B) 中选择 (k - k_1) 个。(B) 中选的一定是单个区间。这样能保证合法(想想为什么)。

    • 按长度排序取前 (k-1) 个,然后剩下的所有分一类。(这就是在上面有区间集合的交集为 (0) 的时候这种贪心才会起作用)

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <cctype>
    #include <algorithm>
    using namespace std;
    #define rep(i, s, t) for(int i = (s), mi = (t); i <= mi; i++)
    #define dwn(i, s, t) for(int i = (s), mi = (t); i >= mi; i--)
     
    int read() {
        int x = 0, f = 1; char c = getchar();
        while(!isdigit(c)){ if(c == '-') f = -1; c = getchar(); }
        while(isdigit(c)){ x = x * 10 + c - '0'; c = getchar(); }
        return x * f;
    }
     
    #define maxn 1000010
    #define LL long long
     
    struct Line {
        int l, r;
        Line() {}
        Line(int _, int __): l(_), r(__) {}
        bool operator == (const Line& t) const { return l == t.l && r == t.r; }
        bool operator < (const Line& t) const { return r != t.r ? r < t.r : l > t.l; }
        Line operator * (const Line& t) const { return Line(max(l, t.l), min(r, t.r)); }
        Line operator *= (const Line& t) { *this = *this * t; return *this; }
    } ls[maxn], getl[maxn], bigl[maxn];
    int n, K, cntg, cntb, val[maxn];
     
    bool cmplen(Line a, Line b) { return a.r - a.l > b.r - b.l; }
     
    int main() {
        n = read(); K = read();
        rep(i, 1, n) {
            int l = read(), r = read();
            ls[i] = Line(l, r);
        }
         
        sort(ls + 1, ls + n + 1);
        for(int i = 1; i <= n; ) {
            getl[++cntg] = ls[i++];
            while(i <= n && ls[i] * ls[i-1] == ls[i-1]) bigl[++cntb] = ls[i++];
        }
        sort(bigl + 1, bigl + cntb + 1, cmplen);
        sort(getl + 1, getl + cntg + 1);
        LL sum = 0, ans = 0;
        rep(i, 1, cntg) sum += getl[i].r - getl[i].l;
        rep(i, 1, cntg - 1) val[i] = getl[i+1].r - getl[i].l;
        sort(val + 1, val + cntg), reverse(val + 1, val + cntg);
        dwn(i, cntg - 1, K) sum -= val[i];
        rep(i, cntg + 1, K) sum += bigl[i-cntg].r - bigl[i-cntg].l;
        int cg, cb;
        if(cntg <= K) cg = cntg, cb = K - cntg;
        else cg = K, cb = 0;
        ans = max(ans, sum);
        for(; cg > 1;) {
            sum -= val[--cg];
            cb++; sum += bigl[cb].r - bigl[cb].l;
            ans = max(ans, sum);
        }
         
        sum = 0;
        sort(ls + 1, ls + n + 1, cmplen);
        rep(i, 1, K - 1) sum += ls[i].r - ls[i].l;
         
        printf("%lld
    ", max(ans, sum));
         
        return 0;
    }
    
  • 相关阅读:
    JavaScript-Runoob-JS 参考手册 :JavaScript 对象
    JavaScript-Runoob-JS 实例 :JavaScript 总结
    JavaScript-Runoob-JS 实例 :JavaScript HTML DOM 实例
    JavaScript-Runoob-JS 实例 :JavaScript Browser 对象实例
    JavaScript-Runoob-JS 实例 :JavaScript 对象实例
    linux 下 php 安装 libevent
    linux 下 php 安装 event
    mybatis实战教程(mybatis in action),mybatis入门到精通
    将MapReduce的结果输出至Mysql数据库
    spring路径通配符
  • 原文地址:https://www.cnblogs.com/xiao-ju-ruo-xjr/p/8323454.html
Copyright © 2011-2022 走看看