zoukankan      html  css  js  c++  java
  • 【lct】bzoj1036 [ZJOI2008]树的统计Count

    题意:给你一棵树,点带权,支持三种操作:单点修改;询问链上和;询问链上max。

    这里的Query操作用了与上一题不太一样的做法(上一题用那种做法,因为在边带权的情况下换根太困难啦):

      先ChangeRoot(U),然后Access(V),再Splay(V),询问V在辅助树中的左子树。

    因为Splay的pushdown用了极为暴力的做法……故而跑得比原来写的链剖线段树慢一倍。不过常数不在意了。

    #include<cstdio>
    #include<iostream>
    #include<stack>
    #include<cstring>
    #include<algorithm>
    using namespace std;
    #define maxn 30005
    int fa[maxn],c[maxn][2],siz[maxn];
    bool is_root[maxn],delta[maxn];
    int val[maxn],totalval[maxn],maxv[maxn];
    void Mark(int x){
        if(x){
            delta[x]^=1;
        }
    }
    void Maintain(int x)
    {
        siz[x]=siz[c[x][0]]+siz[c[x][1]]+1;
        totalval[x]=totalval[c[x][0]]+totalval[c[x][1]]+val[x];
        maxv[x]=val[x];
        if(c[x][0]){
        	maxv[x]=max(maxv[x],maxv[c[x][0]]);
        }
        if(c[x][1]){
        	maxv[x]=max(maxv[x],maxv[c[x][1]]);
        }
    }
    void pushdown(int x){
        if(delta[x]){
            Mark(c[x][0]);
            Mark(c[x][1]);
            swap(c[x][0],c[x][1]);
            delta[x]=0;
        }
    }
    void Rotate(int x,bool flag)
    {
        int y=fa[x];
        c[y][!flag]=c[x][flag];
        if(c[x][flag]){
        	fa[c[x][flag]]=y;
        }
        if(fa[y] && c[fa[y]][c[fa[y]][1]==y]==y){
            c[fa[y]][c[fa[y]][1]==y]=x;
        }
        fa[x]=fa[y];
        c[x][flag]=y;
        fa[y]=x;
        if(is_root[y]){
        	is_root[y]=0;
        	is_root[x]=1;
        }
    	Maintain(y);
    	Maintain(x);
    }
    stack<int>st;
    void Splay(int x)
    {
    	pushdown(x);
        if(!x || is_root[x]){
            return;
        }
    	int U=x;
    	while(!is_root[U]){
    		st.push(U);
    		U=fa[U];
    	}
    	st.push(U);
    	while(!st.empty()){
    		pushdown(st.top());
    		st.pop();
    	}
        int y;
        while(y=fa[x],(!is_root[x])){
            if(is_root[y]){
                Rotate(x,c[y][0]==x);
            }
            else{
                if((c[y][0]==x)==(c[fa[y]][0]==y)){
                    Rotate(y,c[fa[y]][0]==y);
                }
                else{
                    Rotate(x,c[y][0]==x);
                    y=fa[x];
                }
                Rotate(x,c[y][0]==x);
            }
        }
    	Maintain(x);
    }
    void Access(int x){
    	int y;
    	Splay(x);
    	while(fa[x]){
    		y=fa[x];
    		Splay(y);
    		Splay(x);
    		if(c[y][1]){
    			is_root[c[y][1]]=1;
    		}
    		is_root[x]=0;
    		c[y][1]=x;
    		Splay(x);
    	}
    	if(c[x][1]){
    		is_root[c[x][1]]=1;
    		c[x][1]=0;
    	}
    }
    void ChangeRoot(int x){
    	Access(x);
    	Splay(x);
    	Mark(x);
    }
    int QSum(int U,int V){
    	ChangeRoot(U);
    	Access(V);
    	Splay(V);
    	return val[V]+totalval[c[V][0]];
    }
    int QMax(int U,int V){
    	ChangeRoot(U);
    	Access(V);
    	Splay(V);
    	if(!c[V][0]){
    		return val[V];
    	}
    	else{
    		return max(val[V],maxv[c[V][0]]);
    	}
    }
    int n,m;
    int v[maxn<<1],nex[maxn<<1],first[maxn],e;
    void AddEdge(int U,int V){
    	v[++e]=V;
    	nex[e]=first[U];
    	first[U]=e;
    }
    int a[maxn];
    void dfs(int U){
    	siz[U]=1;
    	is_root[U]=1;
    	val[U]=totalval[U]=maxv[U]=a[U];
    	for(int i=first[U];i;i=nex[i]){
    		if(!siz[v[i]]){
    			fa[v[i]]=U;
    			dfs(v[i]);
    		}
    	}
    }
    int main(){
    //	freopen("bzoj1036.in","r",stdin);
    	char op[10];
    	int x,y;
    	scanf("%d",&n);
    	for(int i=1;i<n;++i){
    		scanf("%d%d",&x,&y);
    		AddEdge(x,y);
    		AddEdge(y,x);
    	}
    	for(int i=1;i<=n;++i){
    		scanf("%d",&a[i]);
    	}
    	dfs(1);
    	scanf("%d",&m);
    	for(int i=1;i<=m;++i){
    		scanf("%s%d%d",op,&x,&y);
    		if(op[3]=='N'){
    			Splay(x);
    			val[x]=y;
    			Maintain(x);
    		}
    		else if(op[3]=='M'){
    			printf("%d
    ",QSum(x,y));
    		}
    		else{
    			printf("%d
    ",QMax(x,y));
    		}
    	}
        return 0;
    }
  • 相关阅读:
    js页面跳转(转载)
    insert into select union 插入数据到sqlserver中会自动排列
    一段没用的代码
    gridview中自动生成的列不可以设置只读
    Treeview 简单遍历,赋值,检查 checkbox
    线程操作一个无限循环,cpu 占用 25% 左右
    相对路径,绝对路径互转
    遍历虚拟网站下所有目录
    一个级联关系的表,向上获取各个字段名的函数
    大家用.net 大部分的工作是在干什么
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/7647802.html
Copyright © 2011-2022 走看看