[NOI2015]软件包管理器

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

\(\text{here}\)

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

\(\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{反正不管 你区间修改的时候就把块合并起来。。}\)

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

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

\(\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 = '\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 ;
}

posted @ 2019-09-05 19:22  Isaunoya  阅读(185)  评论(0编辑  收藏  举报
TOP