• [NOI2015]软件包管理器


    ( ext{感谢 @狸狸养的敏敏 面对面教我ODT 帮他宣传一波(划掉)})

    ( ext{here})

    ( ext{如果你不会树链剖分 请去模板题。})

    ( ext{ODT , Old Driver Tree , 就是一种数据结构 你修改越多 这个算法的复杂度越低。})

    ( ext{操作大概是这个样子的 : 用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}) ;
    
    

    ( ext{反正不管 你区间修改的时候就把块合并起来。。})

    ( ext{所以按照这个思路 我们可以先建一个大块。。因为初始是1-n 都是0})

    ( ext{然后你在修改之前查询一下区间的值。。修改之后就是 (r - l + 1) * val})
    ( ext{返回绝对值即可。。})

    (mathcal{Code})

    //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 = '
    ') { 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 ;
    }
    
    
  • 相关阅读:
    javascript 之迭代器
    前端数据结构--二叉树先序、中序、后序 递归、非递归遍历
    前端数据结构--树
    前端数据结构--散列表(哈希表)
    前端数据结构--线性结构-队列、栈
    前端数据结构--线性结构-链表
    前端数据结构--线性结构-数组
    前端数据结构---复杂度分析
    前端数据结构---相关基础概念
    css整理之-----------基本知识
  • 原文地址:https://www.cnblogs.com/qf-breeze/p/11469118.html
Copyright © 2020-2023  润新知