[NOI2015]軟件包管理器

\(\text{感謝 @狸狸養的敏敏 面對面教我ODT 幫他宣傳一波(劃掉)}\)node

\(\text{here}\)c++

\(\text{若是你不會樹鏈剖分 請去模板題。}\)git

\(\text{ODT , Old Driver Tree , 就是一種數據結構 你修改越多 這個算法的複雜度越低。}\)算法

\(\text{操做大概是這個樣子的 : 用set 維護 n 個塊(n指的是序列長度)}\)數據結構

struct node {
    int l ; int r ;
    mutable int val ;
    bool operator < (const node & x) const {
        return l < x.l ;
    }
};
set < node > s ;

#define slt set < node > :: iterator
...
n = read() ;
s.insert({1 , n + 1 , 0}) ;

\(\text{反正無論 你區間修改的時候就把塊合併起來。。}\)spa

\(\text{因此按照這個思路 咱們能夠先建一個大塊。。由於初始是1-n 都是0}\)code

\(\text{而後你在修改以前查詢一下區間的值。。修改以後就是 (r - l + 1) * val}\)
\(\text{返回絕對值便可。。}\)blog

\(\mathcal{Code}\)get

//Isaunoya
#include<bits/stdc++.h>
using namespace std ;
inline int read() { register int x = 0 ; register int f = 1 ; register char c = getchar() ;
    for( ; ! isdigit(c) ; c = getchar()) if(c == '-') f = -1 ;
    for( ; isdigit(c) ; c = getchar()) x = (x << 1) + (x << 3) + (c & 15) ;
    return x * f ;
} int st[105] ;
template < typename T > inline void write(T x , char c = '\n') { int tp = 0 ;
    if(x == 0) return (void) puts("0") ;
    if(x < 0) putchar('-') , x = -x ;
    for( ; x ; x /= 10) st[++ tp] = x % 10 ;
    for( ; tp ; tp --) putchar(st[tp] + '0') ;
    putchar(c) ;
}
//#define Online_Judge

struct node {
    int l ; int r ;
    mutable int val ;
    bool operator < (const node & x) const {
        return l < x.l ;
    }
};
set < node > s ;

#define slt set < node > :: iterator
inline slt Split(int pos) {
    slt it = s.lower_bound((node) {pos}) ;
    if(it != s.end() && it -> l == pos) return it ;
    -- it ;
    int l = it -> l ;
    int r = it -> r ;
    int val = it -> val ;
    s.erase(it) ;
    s.insert({l , pos - 1 , val}) ;
    return s.insert({pos , r , val}).first ;
}
inline int Assign(int l , int r , int val) {
    slt it2 = Split(r + 1) ;
    slt it1 = Split(l) ;
    int sum = 0 ;
    int sum2 = (r - l + 1) * val  ;
    for(slt it = it1 ; it != it2 ; it ++) sum += (it -> r - it -> l + 1) * it -> val ;
    s.erase(it1 , it2) ;
    s.insert({l , r , val}) ;
    return abs(sum - sum2) ;
}
int n ;
struct Node {
    int v ;
    int nxt ;
};
const int N = 1e5 + 10 ;
Node e[N << 1] ;
int cnt = 0 ;
int head[N] ;
inline void Add(int u , int v) {
    e[++ cnt].v = v ;
    e[cnt].nxt = head[u] ;
    head[u] = cnt ;
    return ;
}
int top[N] ;
int id[N] ; int size[N] ;
int d[N] ; int idx = 0 ;
int fa[N] ; int son[N] ;
inline void Dfs1(int u) {
    size[u] = 1 ;
    for(register int i = head[u] ; i ; i = e[i].nxt ) {
        int v = e[i].v ;
        if(v == fa[u]) continue ;
        d[v] = d[u] + 1 ;
        fa[v] = u ;
        Dfs1(v) ;
        size[u] += size[v] ;
        if(size[v] > size[son[u]]) son[u] = v ;
    }
    return ;
}
inline void Dfs2(int u , int t) {
    id[u] = ++ idx ;
    top[u] = t ;
    if(! son[u]) return ;
    Dfs2(son[u] , t) ;
    for(register int i = head[u] ; i ; i = e[i].nxt) {
        int v = e[i].v ;
        if((v ^ fa[u]) && (v ^ son[u])) Dfs2(v , v) ;
    }
}
inline int getopt() { string s = "" ;
    register char c = getchar() ;
    while(isspace(c)) c = getchar() ;
    while(! isspace(c)) {
        s += c ;
        c = getchar() ;
    }
    if(s == "install") return 1 ;
    if(s == "uninstall") return 0 ;
}
inline int Change_Range(int x , int y) {
    int fx = top[x] ;
    int fy = top[y] ;
    int ans = 0 ;
    while(fx ^ fy) {
        if(d[fx] < d[fy]) swap(x , y) , swap(fx , fy) ;
        ans += Assign(id[fx] , id[x] , 1) ;
        x = fa[fx] ;
        fx = top[x] ;
    }
    if(id[x] > id[y]) swap(x , y) ;
    ans += Assign(id[x] , id[y] , 1) ;
    return ans ;
}
inline int Uninstall(int x) {
    return Assign(id[x] , id[x] + size[x] - 1 , 0) ;
}
signed main() {
#ifdef Online_Judge
    freopen("testdata.in" , "r" , stdin) ;
    freopen("testdata2.out" , "w" , stdout) ;
#endif
    n = read() ;
    s.insert({1 , n + 1 , 0}) ;
    for(register int i = 2 ; i <= n ; i ++) {
        int u = read() ; u ++ ;
        Add(u , i) ;
        Add(i , u) ;
    }
    Dfs1(1) ;
    Dfs2(1 , 1) ;
    for(register int t = read() ; t -- ; ) {
        int opt = getopt() ;
        if(opt == 1) {
            int x = read() ; x ++ ;
            write(Change_Range(x , 1)) ;
        }
        if(opt == 0) {
            int x = read() ; x ++ ;
            write(Uninstall(x)) ;
        }
    }
    return 0 ;
}
相關文章
相關標籤/搜索