zoukankan      html  css  js  c++  java
  • 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
    ", getsum(x, y));
    		} else if(s[1] == 'M' && s[2] == 'a'){
    			LL x, y;
    			scanf("%lld%lld", &x, &y);
    			printf("%lld
    ", getmax(x, y));
    		} else if(s[1] == 'M'){
    			LL x, y;
    			scanf("%lld%lld", &x, &y);
    			printf("%lld
    ", getmin(x, y));
    		} else {
    			LL x, y;
    			scanf("%lld%lld", &x, &y);
    			invert(x, y);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    docker--docker介绍
    docker--虚拟化
    高级运维工程师的打怪升级之路
    mysql常用函数
    CentOS 7 下使用 Firewall
    51nod 1094 和为k的连续区间(map+前缀和)
    51nod 1092 回文字符串(dp)
    51nod 1062 序列中最大的数(打表预处理)
    51nod 1284 2 3 5 7的倍数(容斥原理+反面思考)
    51nod 1347 旋转字符串(思维好题)
  • 原文地址:https://www.cnblogs.com/darklove/p/6874869.html
Copyright © 2011-2022 走看看