• bzoj3307 雨天的尾巴


    传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=3307

    【题解】

    这什么垃圾题啊卡空间卡时间卡栈

    然后我会了一种新姿势:人工栈(好像也不难啊喂)

    我们发现对于每种物品,只需要在u这地方的权值线段树上+1,v的权值线段树上+1,LCA的权值线段树上-1,LCA的父亲权值线段树上-1.

    算一算就会发现符合条件了。

    现在需要的就是合并线段树

    线段树合并是log的,然后就是$O(nlogn)$了

    bzoj上恰好10s。。

    还有一个是,本地实测,极限数据要开到1000w才能过,bzoj卡了空间我只能开600w,居然过了。。

    放两个代码吧(虽然bzoj都能过?)

    直接dfs,开栈命令(?)

    # pragma comment(linker, /STACK:102400000,102400000)
    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 2e5 + 10, N = 6e6 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    namespace SMT {
        int p[N], w[N], ch[N][2], siz;
        
        inline void up(int x) {
            if(w[ch[x][0]] >= w[ch[x][1]]) {
                w[x] = w[ch[x][0]];
                p[x] = p[ch[x][0]];
            } else {
                w[x] = w[ch[x][1]];
                p[x] = p[ch[x][1]];
            } 
        }
        
        inline void edt(int &x, int l, int r, int pos, int d) {
            if(!x) x = ++siz;
            if(l == r) {
                p[x] = l; 
                w[x] += d;
                return ;
            }
            int mid = l+r>>1;
            if(pos <= mid) edt(ch[x][0], l, mid, pos, d);
            else edt(ch[x][1], mid+1, r, pos, d);
            up(x); 
        }
        
        inline int merge(int x, int y, int l, int r) {
            if(!x || !y) return x+y;
            if(l == r) {
                w[x] = w[x] + w[y];
                return x;
            } 
            int mid = l+r>>1;
            ch[x][0] = merge(ch[x][0], ch[y][0], l, mid);
            ch[x][1] = merge(ch[x][1], ch[y][1], mid+1, r);
            up(x); 
            return x;
        }
    }
    
    int head[M], nxt[M], to[M], tot=0; 
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    inline void adde(int u, int v) {
        add(u, v), add(v, u);
    }
    
    int n, m, rt[M];
    int fa[M][17], dep[M];
    inline void dfs(int x, int father) {
         dep[x] = dep[father] + 1;
        fa[x][0] = father;
        for (int i=1; i<=16; ++i) fa[x][i] = fa[fa[x][i-1]][i-1];
        for (int i=head[x]; i; i=nxt[i]) {
            if(to[i] == father) continue;
            dfs(to[i], x);
        }
    }
    
    inline int lca(int u, int v) {
        if(dep[u] < dep[v]) swap(u, v);
        for (int i=16; ~i; --i)
            if((dep[u]-dep[v]) & (1<<i)) u = fa[u][i];
        if(u == v) return u;
        for (int i=16; ~i; --i) 
            if(fa[u][i] != fa[v][i]) {
                u = fa[u][i];
                v = fa[v][i];
            }
        return fa[u][0];
    }
    
    int ans[M]; 
    
    inline void gans(int x) {
        for (int i=head[x]; i; i=nxt[i]) {
            if(to[i] == fa[x][0]) continue;
            gans(to[i]); 
            rt[x] = SMT::merge(rt[x], rt[to[i]], 1, 1e9);
        }
        ans[x] = SMT::p[rt[x]]; 
    }
    
    
    int main() {
    //    freopen("3307.in", "r", stdin);
    //    freopen("3307.out", "w", stdout); 
        cin >> n >> m;
        for (int i=1, u, v; i<n; ++i) {
             scanf("%d%d", &u, &v);
            adde(u, v);
        }
        dfs(1, 0); 
        for (int i=1, u, v, z; i<=m; ++i) {
             scanf("%d%d%d", &u, &v, &z);
            int LCA = lca(u, v);
            SMT::edt(rt[u], 1, 1e9, z, 1);
            SMT::edt(rt[v], 1, 1e9, z, 1);
            SMT::edt(rt[LCA], 1, 1e9, z, -1); 
            if(LCA != 1) SMT::edt(rt[fa[LCA][0]], 1, 1e9, z, -1);
        }
        
        gans(1); 
        for (int i=1; i<=n; ++i) printf("%d
    ", ans[i]); 
    
        return 0;
    }
    View Code

    人工栈

    # include <queue>
    # include <stdio.h>
    # include <string.h>
    # include <iostream>
    # include <algorithm>
    // # include <bits/stdc++.h>
    
    using namespace std;
    
    typedef long long ll;
    typedef long double ld;
    typedef unsigned long long ull;
    const int M = 2e5 + 10, N = 6e6 + 10;
    const int mod = 1e9+7;
    
    # define RG register
    # define ST static
    
    namespace SMT {
        int p[N], w[N], ch[N][2], siz;
        
        inline void up(int x) {
            if(w[ch[x][0]] >= w[ch[x][1]]) {
                w[x] = w[ch[x][0]];
                p[x] = p[ch[x][0]];
            } else {
                w[x] = w[ch[x][1]];
                p[x] = p[ch[x][1]];
            } 
        }
        
        inline void edt(int &x, int l, int r, int pos, int d) {
            if(!x) x = ++siz;
            if(l == r) {
                w[x] += d;
                if(w[x] <= 0) p[x] = 0;
                else p[x] = l; 
                return ;
            }
            int mid = l+r>>1;
            if(pos <= mid) edt(ch[x][0], l, mid, pos, d);
            else edt(ch[x][1], mid+1, r, pos, d);
            up(x); 
        }
        
        inline int merge(int x, int y, int l, int r) {
            if(!x || !y) return x+y;
            if(l == r) {
                w[x] = w[x] + w[y];
                if(w[x] <= 0) p[x] = 0;
                else p[x] = l; 
                return x;
            } 
            int mid = l+r>>1;
            ch[x][0] = merge(ch[x][0], ch[y][0], l, mid);
            ch[x][1] = merge(ch[x][1], ch[y][1], mid+1, r);
            up(x); 
            return x;
        }
        
        inline void prt(int x, int l, int r) {
            if(!x) return ; 
            printf("%d %d %d %d %d
    ", x, l, r, p[x], w[x]);
            if(l == r) return;
            int mid = l+r>>1;
            prt(ch[x][0], l, mid); 
            prt(ch[x][1], mid+1, r);
        }
    }
    
    int head[M], nxt[M], to[M], tot=0; 
    inline void add(int u, int v) {
        ++tot; nxt[tot] = head[u]; head[u] = tot; to[tot] = v;
    }
    inline void adde(int u, int v) {
        add(u, v), add(v, u);
    }
    
    int n, m, rt[M];
    int fa[M][17], dep[M];
    bool vis[M]; 
    queue<int> q;
    inline void bfs(int x) {
        q.push(x); dep[x] = 1; 
        while(!q.empty()) {
            int top = q.front(); q.pop(); vis[top] = 1; 
            for (int i=1; i<=16; ++i) fa[top][i] = fa[fa[top][i-1]][i-1];
            for (int i=head[top]; i; i=nxt[i]) {
                if(!vis[to[i]]) {
                    fa[to[i]][0] = top;
                    dep[to[i]] = dep[top] + 1; 
                    q.push(to[i]); 
                }
            }
        }
    }
    
    inline int lca(int u, int v) {
        if(dep[u] < dep[v]) swap(u, v);
        for (int i=16; ~i; --i)
            if((dep[u]-dep[v]) & (1<<i)) u = fa[u][i];
        if(u == v) return u;
        for (int i=16; ~i; --i) 
            if(fa[u][i] != fa[v][i]) {
                u = fa[u][i];
                v = fa[v][i];
            }
        return fa[u][0];
    }
    
    int ans[M]; 
    int st[M], cur[M], stn=0; 
    inline void gans(int start) {
        int x, t;
        st[++stn] = start;
        while(stn) {
            x = st[stn];
            if(to[cur[x]] == fa[x][0]) cur[x] = nxt[cur[x]]; 
            if(!cur[x]) {
                --stn;
                ans[x] = SMT::p[rt[x]];
    //            printf("==================%d=================
    ", x);
    //            SMT::prt(rt[x], 1, 1e9); 
                t = fa[x][0];
                if(t) rt[t] = SMT::merge(rt[t], rt[x], 1, 1e9);
            } else { 
                t = to[cur[x]];
                st[++stn] = t;
                cur[x] = nxt[cur[x]];
            }
        } 
    }
    
    
    int main() {
    //    freopen("3307.in", "r", stdin);
    //    freopen("3307.out", "w", stdout); 
        cin >> n >> m;
        for (int i=1, u, v; i<n; ++i) {
             scanf("%d%d", &u, &v);
            adde(u, v);
        }
        bfs(1); 
        for (int i=1, u, v, z; i<=m; ++i) {
             scanf("%d%d%d", &u, &v, &z);
            int LCA = lca(u, v);
            SMT::edt(rt[u], 1, 1e9, z, 1);
            SMT::edt(rt[v], 1, 1e9, z, 1);
            SMT::edt(rt[LCA], 1, 1e9, z, -1);  
            if(LCA != 1) SMT::edt(rt[fa[LCA][0]], 1, 1e9, z, -1);
        }
        
        for (int i=1; i<=n; ++i) cur[i] = head[i]; 
        gans(1); 
        for (int i=1; i<=n; ++i) printf("%d
    ", ans[i]); 
    
        return 0;
    }
    /*
    5 5
    1 2
    2 3
    3 4
    4 5
    1 2 1
    2 3 1
    1 3 1
    1 4 2
    3 4 2
    */
    View Code
  • 相关阅读:
    封装 lhgDialog弹出窗口组件 为C#的api
    最简单的dbhelper类
    asp.net无组件导出Excel
    js中的escape的用法汇总
    【Demo 0110】获取内存信息
    【Demo 0119】延时加载DLL 编程
    【Demo 0112】共享数据段
    【Demo 0116】堆的使用
    【Demo 0111】获取进程当前内存使用
    【Demo 0118】动态加载DLL
  • 原文地址:https://www.cnblogs.com/galaxies/p/bzoj3307.html
Copyright © 2020-2023  润新知