zoukankan      html  css  js  c++  java
  • 【ZJOI 2008】树的统计 Count

    看题目的出门左拐:

      http://www.zybbs.org/JudgeOnline/problem.php?id=1036  

      题目大意:给定一棵加权树,实现修改任意节点权值,求两点间路径最大值和权值和的操作。

      看到题目想都没想就LCT了,敲啊敲、敲啊敲……本来YY着1A的,然后发现WA了……第一个点就WA了……

      囧……分析了好半天……睡了一觉……猛然想起自己宏定义的INF……

      原来宏定义INF ~0u>>1然后赋值-INF会出问题的- -

      我对C++了解不熟……学习了……

    #include <iostream>
    #include <cstdio>
    #include <cstdlib>
    #include <cstring>
    #include <queue>
    #define NIL LCT
    #define INF 0x7f7f7f7f
    #define mn 130001
    #define mm 300000
    using namespace std;
    template<class T>inline void gmax(T &a,T b){if(a<b)a=b;}
    
    queue<int> q;
    int n,m,a,b,value[mn];
    char s[10];
    struct EDGE{
    	int pnt;
    	EDGE *pre;
    	EDGE (){}
    	EDGE(int _pnt,EDGE *_pre):pnt(_pnt),pre(_pre){}
    }Edge[mm*2],*SP=Edge,*edge[mm];
    
    inline void addedge(int a,int b){
    	edge[a]=new(++SP)EDGE(b,edge[a]);
    	edge[b]=new(++SP)EDGE(a,edge[b]);
    }
    
    struct LinkCutTree{
    	struct NODE{
    		int val,maxn,sum;
    		bool root;
    		NODE *left,*right,*father;
    		NODE (){}
    		NODE(int _val,NODE *_left,NODE *_right,NODE *_father):
    			val(_val),left(_left),right(_right),father(_father){root=true;}
    	}LCT[mn],*NP,*node[mn];
    	
    	void init(){
    		NP=NIL;
    		NIL->val=NIL->maxn=-INF;NIL->sum=0;
    		NIL->left=NIL->right=NIL->father=NIL;
    		NIL->root=false;
    	}
    	
    	void build(){
    		q.push(1);
    		node[1]=new(++NP)NODE(value[1],NIL,NIL,NIL);
    		while(!q.empty()){
    			int i=q.front();q.pop();
    			for(EDGE *j=edge[i];j;j=j->pre)
    				if(node[j->pnt]!=node[i]->father){
    					node[j->pnt]=new(++NP)NODE(value[j->pnt],NIL,NIL,node[i]);
    					q.push(j->pnt);
    				}
    		}
    	}
    	
    	void update(NODE *&t){
    		t->sum=t->left->sum+t->right->sum+t->val;
    		t->maxn=max(t->val,max(t->left->maxn,t->right->maxn));
    	}
    	
    	void zig(NODE *&t){
    		NODE *f=t->father,*r=t->right;
    		t->father=f->father;
    		if(f->root){
    			t->root=true;
    			f->root=false;
    		}else{
    			if(f->father->left==f) f->father->left=t;
    			else f->father->right=t;
    		}
    		t->right=f,f->father=t,f->left=r,r->father=f;
    		update(f);
    	}
    	
    	void zag(NODE *&t){
    		NODE *f=t->father,*l=t->left;
    		t->father=f->father;
    		if(f->root){
    			t->root=true;
    			f->root=false;
    		}else{
    			if(f->father->left==f) f->father->left=t;
    			else f->father->right=t;
    		}
    		t->left=f;f->father=t,f->right=l,l->father=f;
    		update(f);
    	}
    	
    	void splay(NODE *&t){
    		while(!t->root){
    			if(t->father->root){
    				if(t->father->left==t) zig(t);
    				else zag(t);
    			}else{
    				if(t->father->father->left==t->father){
    					if(t->father->left==t) zig(t->father),zig(t);
    					else zag(t),zig(t);
    				}else{
    					if(t->father->left==t) zig(t),zag(t);
    					else zag(t->father),zag(t);
    				}
    			}
    		}
    		update(t);
    	}
    	
    	void Expose(NODE *&t){
    		NODE *p=t,*q=NIL;
    		while(p!=NIL){
    			splay(p);
    			p->right->root=true;
    			p->right=q;
    			p->right->root=false;
    			update(p);
    			q=p,p=p->father;
    		}
    	}
    	
    	void Modify(int t,int key){
    		node[t]->val=key;
    		update(node[t]);
    		splay(node[t]);
    	}
    	
    	void queryMax(int a,int b){
    		Expose(node[a]);
    		NODE *p=node[b],*q=NIL;
    		while(p!=NIL){
    			splay(p);
    			if(p->father==NIL) printf("%d\n",max(p->val,max(p->right->maxn,q->maxn)));
    			p->right->root=true;
    			p->right=q;
    			p->right->root=false;
    			update(p);
    			q=p,p=p->father;
    		}
    	}
    	
    	void querySum(int a,int b){
    		Expose(node[a]);
    		NODE *p=node[b],*q=NIL;
    		while(p!=NIL){
    			splay(p);
    			if(p->father==NIL)printf("%d\n",p->right->sum+q->sum+p->val);
    			p->right->root=true;
    			p->right=q;
    			p->right->root=false;
    			update(p);
    			q=p,p=p->father;
    		}
    	}
    }tree;
    
    int main(){
    	scanf("%d",&n);
    	for(int i=1;i<n;i++){
    		scanf("%d%d",&a,&b);
    		addedge(a,b);
    	}
    	for(int i=1;i<=n;i++) scanf("%d",&value[i]);
    	tree.init();
    	tree.build();
    	scanf("%d\n",&m);
    	while(m--){
    		scanf("%s",s);
    		scanf("%d%d",&a,&b);
    		switch(s[1]){
    			case 'M':
    				tree.queryMax(a,b);
    				break;
    			case 'S':
    				tree.querySum(a,b);
    				break;
    			case 'H':
    				tree.Modify(a,b);
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    62. Unique Paths
    102. Binary Tree Level Order Traversal
    3、公共接口不应该使用太过频繁,当有大量类型实现公共接口时,应当避免通过公共接口调用对象
    2、Task 使用 ContinueWith 而不要使用 Wait
    1、使用 as 而不要用 is
    VS 超级好用的 Ctrl E E
    一个好用的分组算法2
    java 字典 map 和 list.forEach
    mongo windows 安装
    mongo repository
  • 原文地址:https://www.cnblogs.com/Delostik/p/2129520.html
Copyright © 2011-2022 走看看