zoukankan      html  css  js  c++  java
  • Codeforces Round #425 (Div. 2) D 树链剖分 + 树状数组维护区间

    一看就知道 可以LCA判断做 也可以树链剖分拿头暴力

    然而快速读入和线段树维护区间会T70 于是只能LCA?

    线段树的常数不小 于是需要另外一种办法来进行区间加减和查询区间和 就是使用树状数组

    这个题的代码

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<cstring>
    using namespace std;
    #define pb push_back
    
    int n , qn ;
    vector<int > q [100050] ;
    int top[100050] , fa[100050] , deep[100050] , num[100050] , p[100050] , fp[100050] , son[100050] , pos ;
    
    inline int read()
    {
        int x=0;char ch=getchar();
        while(ch<'0'||ch>'9')ch=getchar();
        while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
        return x;
    }
    
    ///----------
    
    int c[100050] ;
    int d[100050] ;
    int lowbit(int x) {
        return (x & (-x)) ;
    }
    void add(int c[] , int x ,int val) {
        while(x <= n+5) {
            c[x] += val ; x += lowbit(x) ;
        }
    }
    int sum(int c[] , int x) {
        int res = 0 ;
        while(x > 0) {
            res += c[x] ;
            x -= lowbit(x) ;
        }
        return res ;
    }
    void add(int l , int r , int val) {
        add(c , l , val) ; add(d , l , l * val) ;
        add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ;
    }
    int sum(int x) {
        return (x + 1) * sum(c , x) - sum(d , x) ;
    }
    int sum(int l , int r) {
        return sum(r) - sum(l - 1) ;
    }
    
    ///----------
    
    void dfs1(int u , int pre , int d) {
        deep[u] = d ;
        fa[u] = pre ;
        num[u] = 1 ;
        for(int i = 0 ; i < q[u].size() ; i ++ ) {
            int v = q[u][i] ;
            if(v != pre) {
                dfs1(v , u , d+1) ;
                num[u] += num[v] ;
                if(son[u] == -1 || num[v] > num[son[u]]) {
                    son[u] = v ;
                }
            }
        }
    }
    void getpos(int u , int sp) {
        top[u] = sp ;
        p[u] = pos ++ ;
        fp[p[u]] = u ;
        if(son[u] == -1) return ;
        getpos(son[u] , sp) ;
        for(int i = 0 ; i < q[u].size() ; i ++ ) {
            int v = q[u][i] ;
            if(v != son[u] && v != fa[u]) {
                getpos(v , v) ;
            }
        }
    }
    void chang(int u , int v , int val) {
        int f1 = top[u] , f2 = top[v] ;
        int tmp = 0 ;
        while(f1 != f2) {
            if(deep[f1] < deep[f2]) {
                swap(f1 , f2) ; swap(u , v) ;
            }
            add(p[f1] , p[u] , val) ;
            u = fa[f1] ;
            f1 = top[u] ;
        }
        if(deep[u] > deep[v]) swap(u , v) ;
        add(p[u] , p[v] , val) ;
    }
    int que(int u , int v) {
        int f1 = top[u] , f2 = top[v] ;
        int tmp = 0 ;
        while(f1 != f2) {
            if(deep[f1] < deep[f2]) {
                swap(f1 , f2) ; swap(u , v) ;
            }
            tmp += sum(p[f1] , p[u]) ;
            u = fa[f1] ;
            f1 = top[u] ;
        }
        if(deep[u] > deep[v]) swap(u , v) ;
        tmp += sum(p[u] , p[v]) ;
        return tmp ;
    }
    
    int main () {
        n = read() ;
        qn = read() ;
        for(int i = 2 ; i <= n ; i ++ ) {
            int z ; z = read() ;
            q[z].pb(i) ; q[i].pb(z) ;
        }
        memset(son , -1 , sizeof(son)) ;
        pos = 1 ;
        dfs1(1,0,0) ;
        getpos(1 , 1) ;
        while(qn -- ) {
            int aa , bb , cc ;
            aa = read() ; bb = read() ; cc = read() ;
    
            int ans = 0 ;
    
            chang(aa,bb,1) ;
            ans = max(que(bb,cc) , ans) ;
            chang(aa,bb,-1) ;
    
    
            chang(aa,cc,1) ;
            ans = max(que(bb,cc) , ans) ;
            chang(aa,cc,-1) ;
    
    
            chang(aa,bb,1) ;
            ans = max(que(aa,cc) , ans) ;
            chang(aa,bb,-1) ;
    
            printf("%d
    " , ans) ;
        }
    }
    

     其中的树状数组 拿两个数组来分别维护 具体代码

    int c[100050] ;
    int d[100050] ;
    int lowbit(int x) {
        return (x & (-x)) ;
    }
    void add(int c[] , int x ,int val) {
        while(x <= n+5) {
            c[x] += val ; x += lowbit(x) ;
        }
    }
    int sum(int c[] , int x) {
        int res = 0 ;
        while(x > 0) {
            res += c[x] ;
            x -= lowbit(x) ;
        }
        return res ;
    }
    void add(int l , int r , int val) {
        add(c , l , val) ; add(d , l , l * val) ;
        add(c , r+1 , -val ) ; add(d , r + 1 , -val * (r+1)) ;
    }
    int sum(int x) {
        return (x + 1) * sum(c , x) - sum(d , x) ;
    }
    int sum(int l , int r) {
        return sum(r) - sum(l - 1) ;
    }
    

    树状数组天下无敌TAT 于是又上网学习了新姿势 我有姿势我自豪

    树状数组单点修改 + 区间查询max

    int num[5000] ;
    int c[5000] ;
    int n ;
    int lowbit(int x)
    {
        return x & (-x);
    }
    void updata(int x)
    {
        int lx, i;
        while (x <= n)
        {
            c[x] = num[x];
            lx = lowbit(x);
            for (i=1; i<lx; i<<=1)
                c[x] = max(c[x], c[x-i]);
            x += lowbit(x);
        }
    }
    int query(int L, int R)
    {
        int ans = 0;
        while (R >= L)
        {
            ans = max(num[R], ans);
            R --;
            for (; R-lowbit(R) >= L; R -= lowbit(R))
                ans = max(c[R], ans);
        }
        return ans;
    }
    

    以及这里还有...矩形增减 + 矩形查询和的黑科技。。。

    http://blog.csdn.net/lawrence_jang/article/details/8054173

  • 相关阅读:
    AUDIT审计的一些使用
    HOW TO PERFORM BLOCK MEDIA RECOVERY (BMR) WHEN BACKUPS ARE NOT TAKEN BY RMAN. (Doc ID 342972.1)
    使用BBED理解和修改Oracle数据块
    Using Class of Secure Transport (COST) to Restrict Instance Registration in Oracle RAC [ID 1340831.1]
    调试利器GDB概念
    第4章 思科IOS
    第3章 ip地址和子网划分
    第2章 TCPIP
    2020年阅读过的黑客资源推荐篇
    第1章 计算机网络
  • 原文地址:https://www.cnblogs.com/rayrayrainrain/p/7255537.html
Copyright © 2011-2022 走看看