bzoj3159: 决战

呀智障选手都快忘了代码怎么打了..


做这道题干啥咧..

GDOI2017D3T4.. dwjshift说很像这道题,然后就去做了..

然后就做了半个月??


简略解法

就是两棵LCT,一棵维护树的结构,一棵维护权值,两棵树在中序遍历上映射,所以维护一下根对根的映射即可


所以要怎么Access..

对于当前点$x$,在把它旋到当前splay的根的时候可以知道它在这棵splay上的排名

然后就去找对应的那棵权值splay的排名就知道映射的是哪个了啊..

然后.. 就没有然后了吧..


下面是代码呀..

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define LL long long
using namespace std;
const LL Maxn = 50010;
struct node {
	LL y, next;
}a[Maxn*2]; LL first[Maxn], len;
LL _max(LL x, LL y) { return x > y ? x : y; }
LL _min(LL x, LL y) { return x < y ? x : y; }
void ins(LL x, LL y) {
	len++;
	a[len].y = y;
	a[len].next = first[x]; first[x] = len;
}
LL n, m, r;
LL p[Maxn];
LL Maxx[Maxn], Minn[Maxn], sum[Maxn], val[Maxn];
LL vfa[Maxn], fa[Maxn], sizef[Maxn], sizev[Maxn];
LL cf[Maxn][2], cv[Maxn][2];
LL revf[Maxn], revv[Maxn], la[Maxn];
LL sta[Maxn], tp;
char s[10];
void dfs(LL x) {
	p[x] = x; sizef[x] = sizev[x] = 1;
	for(LL k = first[x]; k; k = a[k].next){
		LL y = a[k].y;
		if(y == fa[x]) continue;
		fa[y] = x; vfa[y] = x;
		dfs(y);
	}
}
LL rt;
/*f*/
bool is_rootf(LL x) { return cf[fa[x]][0] != x && cf[fa[x]][1] != x; }
void push_downf(LL x) {
	if(revf[x]){
		swap(cf[x][0], cf[x][1]);
		revf[cf[x][0]] ^= 1; revf[cf[x][1]] ^= 1;
		revf[x] = 0;
	}
}
void prepf(LL x) {
	LL i; tp = 0;
	for(i = x; !is_rootf(i); i = fa[i]) sta[++tp] = i;
	sta[++tp] = i;
	for(i = tp; i >= 1; i--) push_downf(sta[i]);
}
void updatef(LL x) { sizef[x] = sizef[cf[x][0]]+sizef[cf[x][1]]+1; }
void rotatef(LL x) {
	LL y = fa[x], z = fa[y], l, r;
	if(cf[y][0] == x) l = 0; else l = 1; r = l^1;
	if(!is_rootf(y)){ if(cf[z][0] == y) cf[z][0] = x; else cf[z][1] = x; }
	fa[x] = z; fa[y] = x; fa[cf[x][r]] = y;
	cf[y][l] = cf[x][r]; cf[x][r] = y;
	updatef(y);
}
void splayf(LL x) {
	rt = x;
	prepf(x);
	while(!is_rootf(x)){
		LL y = fa[x], z = fa[y];
		if(!is_rootf(y)){
			if(is_rootf(z)) rt = z;
			if((cf[z][0] == y)^(cf[y][0] == x)) rotatef(x);
			else rotatef(y);
		} else rt = y;
		rotatef(x);
	}
	updatef(x);
}
/*v*/
bool is_rootv(LL x) { return cv[vfa[x]][0] != x && cv[vfa[x]][1] != x; }
void push_downv(LL x) {
	if(revv[x]){
		swap(cv[x][0], cv[x][1]);
		revv[cv[x][0]] ^= 1; revv[cv[x][1]] ^= 1;
		revv[x] = 0;
	}
	if(la[x] > 0){
		if(cv[x][0] > 0){
			sum[cv[x][0]] += sizev[cv[x][0]]*la[x]; val[cv[x][0]] += la[x];
			Maxx[cv[x][0]] += la[x];
			Minn[cv[x][0]] += la[x];
		la[cv[x][0]] += la[x];
		} if(cv[x][1] > 0){
			sum[cv[x][1]] += sizev[cv[x][1]]*la[x]; val[cv[x][1]] += la[x];
			Maxx[cv[x][1]] += la[x];
			Minn[cv[x][1]] += la[x];
			la[cv[x][1]] += la[x];
		}
		la[x] = 0;
	}
}
void prepv(LL x) {
	LL i; tp = 0;
	for(i = x; !is_rootv(i); i = vfa[i]) sta[++tp] = i;
	sta[++tp] = i;
	for(i = tp; i >= 1; i--) push_downv(sta[i]);
}
void updatev(LL x) {
	Maxx[x] = _max(Maxx[cv[x][0]], _max(Maxx[cv[x][1]], val[x]));
	Minn[x] = _min(Minn[cv[x][0]], _min(Minn[cv[x][1]], val[x]));
	sum[x] = sum[cv[x][0]]+sum[cv[x][1]]+val[x];
	sizev[x] = sizev[cv[x][0]]+sizev[cv[x][1]]+1;
}
void rotatev(LL x) {
	LL y = vfa[x], z = vfa[y], l, r;
	if(cv[y][0] == x) l = 0; else l = 1; r = l^1;
	if(!is_rootv(y)){ if(cv[z][0] == y) cv[z][0] = x; else cv[z][1] = x; }
	vfa[x] = z; vfa[y] = x; vfa[cv[x][r]] = y;
	cv[y][l] = cv[x][r]; cv[x][r] = y;
	updatev(y);
}
void splayv(LL x) {
	prepv(x);
	while(!is_rootv(x)){
		LL y = vfa[x], z = vfa[y];
		if(!is_rootv(y)){
			if((cv[z][0] == y)^(cv[y][0] == x)) rotatev(x);
			else rotatev(y);
		}
		rotatev(x);
	}
	updatev(x);
}
LL find_rank(LL x, LL p) {
	push_downv(x);
	if(sizev[cv[x][0]]+1 == p) return x;
	if(sizev[cv[x][0]] >= p) return find_rank(cv[x][0], p);
	else return find_rank(cv[x][1], p-sizev[cv[x][0]]-1);
}
void splay(LL x) {
	splayf(x);
	LL o = find_rank(p[rt], sizef[cf[x][0]]+1);
	splayv(o);
	p[x] = o;
}
void access(LL x) {
	LL tf = 0, tv = 0;
	while(x){
		splay(x);
		LL o = p[x];
		p[cf[x][1]] = cv[o][1];
		cf[x][1] = tf;
		cv[o][1] = tv;
		if(tv) vfa[tv] = o;
		tv = o;
		tf = x;
		x = fa[x];
	}
}
void make_root(LL x) { access(x); splay(x); revf[x] ^= 1; revv[p[x]] ^= 1; }
void getchain(LL x, LL y) { make_root(x); access(y); splay(y); }
LL getsum(LL x, LL y) { getchain(x, y); return sum[p[y]]; }
LL getmin(LL x, LL y) { getchain(x, y); return Minn[p[y]]; }
LL getmax(LL x, LL y) { getchain(x, y); return Maxx[p[y]]; }
void add(LL x, LL y, LL c) { getchain(x, y); sum[p[y]] += sizev[p[y]]*c; val[p[y]] += c; Maxx[p[y]] += c; Minn[p[y]] += c; la[p[y]] += c; }
void invert(LL x, LL y) { getchain(x, y); revv[p[y]] ^= 1; }
int main() {
	LL i, j, k;
	Maxx[0] = -0x7fffffff; Minn[0] = 0x7fffffff;
	scanf("%lld%lld%lld", &n, &m, &r);
	for(i = 1; i < n; i++){
		LL x, y;
		scanf("%lld%lld", &x, &y);
		ins(x, y); ins(y, x);
	}
	dfs(r);
	for(i = 1; i <= m; i++){
		scanf("%s", s+1);
		if(s[1] == 'I' && s[3] == 'c'){
			LL x, y, c;
			scanf("%lld%lld%lld", &x, &y, &c);
			add(x, y, c);
		} else if(s[1] == 'S'){
			LL x, y;
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", getsum(x, y));
		} else if(s[1] == 'M' && s[2] == 'a'){
			LL x, y;
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", getmax(x, y));
		} else if(s[1] == 'M'){
			LL x, y;
			scanf("%lld%lld", &x, &y);
			printf("%lld\n", getmin(x, y));
		} else {
			LL x, y;
			scanf("%lld%lld", &x, &y);
			invert(x, y);
		}
	}
	return 0;
}

 

posted @ 2017-05-18 18:20  Ra1nbow  阅读(236)  评论(0编辑  收藏  举报