zoukankan      html  css  js  c++  java
  • NOI 模拟赛

    T1

    给一棵树,每次求链第 $k$ 小,之后把这条链赋值为 $(ans imes x + y)space mod space p$

    $n leq 200000$

    sol:

    树剖,每条重链维护一个珂朵莉树,暴力就完事了

    这题不随机复杂度也是对的,因为每次操作完必推平,相当于每次操作最多增加常数个信息量,而珂朵莉树的复杂度是 $O(信息量)$(相同信息会缩到一起),最坏复杂度 $O((n+q)log^2n)$

    #include<bits/stdc++.h>
    #define LL long long
    #define rep(i,s,t) for(register int i = (s),i##end = (t); i <= i##end; ++i)
    #define dwn(i,s,t) for(register int i = (s),i##end = (t); i >= i##end; --i)
    #define int long long
    using namespace std;
    inline int read() {
        int x=0,f=1;char ch;
        for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
        return x*f;
    }
    const int maxn = 400010;
    int n, x, y, p, w[maxn];
    int first[maxn], to[maxn << 1], nx[maxn << 1], cnt;
    inline void add(int u, int v) {
        to[++cnt] = v;
        nx[cnt] = first[u];
        first[u] = cnt;
    }
    int size[maxn], fa[maxn], dep[maxn], bl[maxn], pos[maxn], dfn, reg[maxn];
    void dfs1(int x) {
        size[x] = 1;
        for(int i=first[x];i;i=nx[i]) {
            if(to[i] == fa[x]) continue;
            fa[to[i]] = x;
            dep[to[i]] = dep[x] + 1;
            dfs1(to[i]);
            size[x] += size[to[i]];
        }
    }
    void dfs2(int x, int col) {
        bl[x] = col; pos[x] = ++dfn; reg[dfn] = x;
        int k = 0;
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && size[to[i]] > size[k]) k = to[i];
        if(!k) return;
        dfs2(k, col);
        for(int i=first[x];i;i=nx[i])
            if(to[i] != fa[x] && to[i] != k) dfs2(to[i], to[i]);
    }
    #define ls (x << 1)
    #define rs ((x << 1) | 1)
    #define pii pair<int, int>
    #define mp make_pair
    pii seg[maxn << 2];
    int tag[maxn << 2];
    inline int isfull(int x, int l, int r) {
        return (seg[x].second == (r - l + 1));
    }
    void pushup(int x, int l, int r) {
        int mid = (l + r) >> 1;
        if(seg[ls].first != -1 && seg[rs].first != -1 && seg[ls].first == seg[rs].first) {
            seg[x].first = seg[ls].first;
            seg[x].second = (r - l + 1);
        }
        else seg[x].first = -1;
    }
    void pushdown(int x, int l, int r) {
        if(tag[x]) {
            int mid = (l + r) >> 1;
            seg[ls].first = tag[x]; seg[rs].first = tag[x];tag[ls]=tag[rs]=tag[x]; 
            seg[ls].second = (mid - l + 1), seg[rs].second = r - mid;
            tag[x] = 0;
        }
    }
    void build(int x, int l, int r) {
        seg[x].first = seg[x].second = -1;
        if(l == r) {
            seg[x] = mp(w[reg[l]], 1);
            return;
        }
        int mid = (l + r) >> 1;
        build(ls, l, mid); build(rs, mid + 1, r);
        pushup(x, l, r);
    }
    struct seq {
        int l, r, v;
        seq(){}
        seq(int _1, int _2, int _3): l(_1), r(_2), v(_3) {}
        bool operator < (const seq &b) const {
            return v < b.v;
        }
    }st[maxn]; int top;
    void update(int x, int l, int r, int L, int R, int v) {
        if(L <= l && r <= R) {
            tag[x] = v;
            seg[x].first = v;
            seg[x].second = r - l + 1;
            return;
        }
        pushdown(x, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) update(ls, l, mid, L, R, v);
        if(R > mid) update(rs, mid + 1, r, L, R, v);
        pushup(x, l, r);
    }
    void query(int x, int l, int r, int L, int R) {
        if(L <= l && r <= R) {
            if(seg[x].first != -1) {
                st[++top] = seq(l, r, seg[x].first);
                return;
            }
        }
        pushdown(x, l, r);
        int mid = (l + r) >> 1;
        if(L <= mid) query(ls, l, mid, L, R);
        if(R > mid) query(rs, mid+1, r, L, R);
    }
    int qry(int a, int b, int c) {
        top = 0;
        while(bl[a] != bl[b]) {
            if(dep[bl[a]] < dep[bl[b]]) swap(a, b);
            query(1, 1, n, pos[bl[a]], pos[a]);
            a = fa[bl[a]];
        }
        if(pos[a] > pos[b]) swap(a, b);
        query(1, 1, n, pos[a], pos[b]);
        sort(st + 1, st + top + 1);
        rep(i, 1, top) {
            int len = st[i].r - st[i].l + 1;
            c -= len;
            if(c <= 0) return st[i].v;
        }
    }
    int upd(int a, int b, int c) {
        while(bl[a] != bl[b]) {
            if(dep[bl[a]] < dep[bl[b]]) swap(a, b);
            update(1, 1, n, pos[bl[a]], pos[a], c);
            a = fa[bl[a]];
        }
        if(pos[a] > pos[b]) swap(a, b);
        update(1, 1, n, pos[a], pos[b], c);
    }
    signed main() {
        n = read(), x = read(), y = read(), p = read();
        rep(i, 1, n) w[i] = read();
        rep(i, 2, n) {
            int u = read(), v = read();
            add(u, v); add(v, u);
        } dfs1(1); dfs2(1, 1);
        build(1, 1, n);
        int q = read();
        while(q--) {
            int a = read(), b = read(), c = read();
            int res = qry(a, b, c);
            printf("%lld
    ", res);
            //cout << "upd: " << (1LL * x * res + y) % p + 1 << endl;
            upd(a, b, (1LL * x * res + y) % p + 1);
        }
    }
    View Code

    有点慌,写的很丑,维护了很多没必要的东西

    T2

    给 $n$ 个长方体箱子,把它们套在一起,每个箱子里最多有一个箱子(不一定是一层箱子,也就是箱套箱可以放在箱子里),箱子不能旋转,长宽分别小于等于才能套,求最小总占地面积

    $n leq 200$

    sol:

    首先肯定是算总和 - 最大节省量

    1.可以将箱子间的二维偏序关系看成一个有向图,然后最大费用可行流

    2.可以将箱子间的嵌套关系看成二分图匹配,求一个二分图最优匹配就完事了

    3.可以将每个点拆成出入两个点,每个点限流 $1$,相邻的点连边,$S->入$ ,$出->T$,最大费用可行流

    爱咋做咋做,别 dp 就行

    #include<bits/stdc++.h>
    #define LL long long
    #define rep(i,s,t) for(register int i = (s),i##end = (t); i <= i##end; ++i)
    #define dwn(i,s,t) for(register int i = (s),i##end = (t); i >= i##end; --i)
    using namespace std;
    inline int read()
    {
        int x=0,f=1;char ch;
        for(ch=getchar();!isdigit(ch);ch=getchar())if(ch=='-')f=-f;
        for(;isdigit(ch);ch=getchar())x=10*x+ch-'0';
        return x*f;
    }
    int n;
    struct pos {
        int a,b;
        bool operator < (const pos &y) const {
            if(a == y.a) return b < y.b;
            else return a < y.a;
        }
        bool operator == (const pos &y) const {
            return a == y.a && b == y.b;
        }
    }ps[207];
    const int maxn = 400010;
    struct ZKW {
        #define oo 2147483233
        int n, m, s, t, ans, cost;
        int head[maxn], nx[maxn];
        struct Edge {
            int from, to, caps, cost;
            Edge() {}
            Edge(int _1, int _2, int _3, int _4) : from(_1), to(_2), caps(_3), cost(_4) {}
        } es[maxn];
        void add(int u, int v, int w, int c) {
            es[m] = Edge(u, v, w, c);
            nx[m] = head[u];
            head[u] = m++;
            es[m] = Edge(v, u, 0, -c);
            nx[m] = head[v];
            head[v] = m++;
        }
        ZKW() {
            m = 0;
            ans = 0;
            cost = 0;
            memset(head, -1, sizeof(head));
        }
        queue<int> q;
        int inq[maxn], dis[maxn], vis[maxn];
        int BFS() {
            for (int i = 0; i <= n; i++) dis[i] = -oo;
            dis[t] = 0;
            q.push(t);
            inq[t] = 1;
            while (!q.empty()) {
                int now = q.front();
                q.pop();
                inq[now] = 0;
                for (int i = head[now]; i != -1; i = nx[i]) {
                    Edge &e = es[i ^ 1];
                    if (dis[e.from] < dis[now] + e.cost && e.caps) {
                        dis[e.from] = dis[now] + e.cost;
                        if (!inq[e.from]) {
                            q.push(e.from);
                            inq[e.from] = 1;
                        }
                    }
                }
            }
            if (dis[s] <= 0)return 0;
            cost = dis[s];
            return 1;
        }
        int DFS(int u, int a) {
            if (u == t || !a) {
                ans -= cost * a;
                return a;
            }
            if (vis[u])
                return 0;
            vis[u] = 1;
            int flow = 0, f;
            for (int i = head[u]; i != -1; i = nx[i]) {
                Edge &e = es[i];
                if (dis[e.to] == dis[u] - e.cost && (f = DFS(e.to, min(e.caps, a)))) {
                    flow += f;
                    a -= f;
                    e.caps -= f;
                    es[i ^ 1].caps += f;
                    if (a == 0)
                        return flow;
                }
            }
            return flow;
        }
        int MCMF(int _s, int _t) {
            s = _s, t = _t;
            int flow = 0, f;
            while (BFS()) {
                do {
                    memset(vis, 0, sizeof(vis));
                    f = DFS(s, oo);
                    flow += f;
                } while (f);
            }
            return flow;
        }
    } sol;
    int main()
    {
        n = read();
        rep(i, 1, n) ps[i].a = read(), ps[i].b = read();
        sort(ps + 1, ps + n + 1);
        n = unique(ps + 1 , ps + n + 1) - ps - 1;
        int S = n + n + 1, T = S + 1; sol.n = T + 2;
        rep(i, 1, n)
        {
            sol.ans+=ps[i].a*ps[i].b;
            rep(j, 1, n)
            if(i!=j&&ps[i].a<=ps[j].a&&ps[i].b<=ps[j].b)
                sol.add(i, j+n, 1, ps[i].a*ps[i].b);
            sol.add(S,i,1,0);
            sol.add(i+n,T,1,0);
            //sol.add(i,T,1,0);
        }sol.MCMF(S, T);
        cout << sol.ans << endl;
    }
    View Code

    T3

    求数列 $k$ 次方和

    记 $f(x)$ 为 $k$ 次方和的生成函数,$g(x)$ 为从数列中选出 $k$ 个不同的数乘起来的生成函数

    则 $f(n) = sumlimits_{i=1}^{n-1} f(i) imes g(n-i) imes (-1)^{n-i+1} + n imes g(n)$

    而 $g(x) = prodlimits_{i=1}^n (a_i+1)$ 这个生成函数可以分治 + 卷积

    $f(x)$ 可以 cdq 分治/多项式求逆

    #include <bits/stdc++.h>
    #define LL long long
    #define rep(i, s, t) for (register int i = (s), i##end = (t); i <= i##end; ++i)
    #define dwn(i, s, t) for (register int i = (s), i##end = (t); i >= i##end; --i)
    using namespace std;/*
    const int Size=1<<16;
    char buffer[Size],*head,*tail;
    inline char Getchar() {
        if(head==tail) {
            int l=fread(buffer,1,Size,stdin);
            tail=(head=buffer)+l;
        }
        if(head==tail) return -1;
        return *head++;
    }*/
    inline int read() {
        int x=0,f=1;char c=getchar();
        for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
        for(;isdigit(c);c=getchar()) x=x*10+c-'0';
        return x*f;
    }
    const int mod = 998244353, maxn = 800010;
    int a[maxn], r[maxn], lg[maxn], n, k;
    inline int skr(int x, int t) {
        int res = 1;
        while (t) {
            if (t & 1)
                res = 1LL * res * x % mod;
            x = 1LL * x * x % mod;
            t = t >> 1;
        }
        return res;
    }
    int wn[maxn], iwn[maxn];
    void init(int n) {
        wn[0] = iwn[0] = 1; 
        rep(i, 1, n-1) wn[i] = skr(3, (mod - 1) / (i << 1));
        rep(i, 1, n-1) iwn[i] = skr(332748118, (mod - 1) / (i << 1));
    }
    inline void fft_init(int n) {rep(i, 0, n - 1) r[i] = (r[i >> 1] >> 1) | ((i & 1) << (lg[n] - 1));}
    inline void fft(int *a, int n, int type) {
        rep(i, 0, n - 1) if (i < r[i]) swap(a[i], a[r[i]]);
        for (int i = 1; i < n; i <<= 1) {
            //int wn = skr(3, (mod - 1) / (i << 1));
            //if (type == -1)
            //    wn = skr(wn, mod - 2);
            int twn = (type == -1) ? iwn[i] : wn[i];
            for (int j = 0; j < n; j += (i << 1)) {
                int w = 1;
                for (int k = 0; k < i; k++, w = 1LL * w * twn % mod) {
                    int x = a[j + k], y = 1LL * w * a[j + k + i] % mod;
                    a[j + k] = (x + y) % mod;
                    a[j + k + i] = (x - y + mod) % mod;
                }
            }
        }
        if (type == -1) {
            int inv_n = skr(n, mod - 2);
            rep(i, 0, n - 1) a[i] = 1LL * a[i] * inv_n % mod;
        }
    }
    int A[maxn], B[maxn];
    int C[maxn], D[maxn];
    int mul(int *A, int *B, int len) {
        fft_init(len);
        // fft_init(len);
        fft(A, len, 1);
        // for(int i=0;i<len;i++)cout<<A[i]<<" ";
        // cout<<endl;
        fft(B, len, 1);
        for (int i = 0; i < len; i++) A[i] = (LL)A[i] * B[i] % mod;
        fft(A, len, -1);
        --len;
        while (!A[len]) --len;
        return len;
    }
    vector<int> poly[maxn];
    int solve(int l, int r) {
        if (l == r)
            return poly[l].size() - 1;
        int mid = (l + r) >> 1;
        int ls = solve(l, mid), rs = solve(mid + 1, r);
        int L = 1;
        for (; L <= ls + rs; L <<= 1)
            ;
     
        for (int i = 0; i <= ls; i++) A[i] = poly[l][i];
        for (int i = ls + 1; i < L; i++) A[i] = 0;
     
        for (int i = 0; i <= rs; i++) B[i] = poly[mid + 1][i];
        for (int i = rs + 1; i < L; i++) B[i] = 0;
        poly[l].clear();
        poly[mid + 1].clear();
     
        L = mul(A, B, L);
        for (int i = 0; i <= L; i++) poly[l].push_back(A[i]);
        return L;
    }
    int g[maxn], f[maxn];
    void mulfac(int *A, int *B, int len) {
        fft_init(len);
        fft(A, len, 1);
        fft(B, len, 1);
        for (int i = 0; i < len; i++) A[i] = 1LL * A[i] * B[i] % mod;
        fft(A, len, -1);
    }
    void cdq_fft(int *f, int *g, int l, int r) {
        if (l == r) {
            (f[l] += (1LL * l * g[l] % mod)) %= mod;
            return;
        }
        int mid = (l + r) >> 1;
        cdq_fft(f, g, l, mid);
        int len = 1, ls = 0, rs = 0;
        // for(;len <= ((r - l + mid)<<1);len <<= 1);
        // for(int i=0;i<len;i++)A[i] = B[i] = 0;
        for (int i = l; i <= mid; i++) C[ls++] = f[i];
        for (int i = 1; i <= r - l; i++) D[rs++] = g[i];
        for (; len <= (ls + rs - 1); len <<= 1)
            ;
        mulfac(C, D, len);
        for (int i = mid + 1; i <= r; i++) f[i] = (f[i] + C[i - l - 1]) % mod;
        for (int i = 0; i < len; i++) C[i] = D[i] = 0;
        cdq_fft(f, g, mid + 1, r);
    }
    int main() {
        //freopen("1.in","r",stdin);
        //freopen("1.out","w",stdout);
        lg[0] = -1; init(1 << 19);
        rep(i, 1, maxn - 1) lg[i] = lg[i >> 1] + 1;
            n = read();
            for (int i = 1; i <= n; i++) {
                a[i] = read();
                if(a[i] >= mod) a[i] -= mod;
                poly[i].push_back(1);
                poly[i].push_back(a[i]);
            }
            solve(1, n);
            for (int i = 0; i < poly[1].size(); i++) g[i] = (((i & 1) ? 1 : (-1)) * poly[1][i] + mod) % mod;
            poly[1].clear();
            cdq_fft(f, g, 0, n);
            for (int i = 1; i <= n; i++) printf("%d
    ", f[i]);
    }
    View Code

    这场出了 T2 和 T3

    难度非常悬殊的两道题,一道只有一个人没 A,一道只有一个人 A 了

    过于真实,引起不适

    不出题了QAQ

  • 相关阅读:
    lamp
    ssh 交互脚本
    mysql 备份检测主从脚本
    RANDOM 猜数字脚本
    ansible+playbook 搭建lnmp环境
    集群搭建
    grafana
    nginx lnmp搭建
    shell 基础(1): 变量
    seq 增量输出命令
  • 原文地址:https://www.cnblogs.com/Kong-Ruo/p/10539714.html
Copyright © 2011-2022 走看看