zoukankan      html  css  js  c++  java
  • [SDOI2014]旅行

    题目:洛谷3313、BZOJ3531。

    题目大意:
    给你一棵树,每个点有一个分类和一个值。
    有四种操作:
    1. 修改某个点的分类
    2. 修改某个点的值
    3. 查询两个分类相同的点的最短路上,与这两个点分类相同的所有点的值的和
    4. 查询两个分类相同的点的最短路上,与这两个点分类相同的所有点的值的最大值

    解题思路:
    树链剖分。
    给每个分类建一棵线段树维护。
    内存不够怎么办?
    动态开点即可。我用了指针+内存池大法。

    C++ Code:

    #include<bits/stdc++.h>
    #define N 100005
    int n,q,w[N],c[N],cnt=0,head[N],son[N],dep[N],fa[N],sz[N],top[N],dfn[N],idx=0,tp=0;
    char opt[5];
    struct node{
    	node *ld,*rd;
    	int sum,max;
    }P[5000001],*STK[5000001];
    inline node* newnode(){
    	node* p=STK[tp--];
    	p->ld=p->rd=NULL;
    	p->sum=0;p->max=-0x3f3f3f3f;
    	return p;
    }
    inline void delnode(node*& rt){
    	STK[++tp]=rt;
    	rt=NULL;
    }
    class SegmentTree{
    	private:
    		int val,id,L,R;
    		void ADD(node*& rt,int l,int r){
    			if(rt==NULL)rt=newnode();
    			if(l==r)rt->sum=rt->max=val;else{
    				int mid=(l+r)>>1;
    				if(id<=mid)ADD(rt->ld,l,mid);else
    				ADD(rt->rd,mid+1,r);
    				int sum=0,max=-0x3f3f3f3f;
    				if(rt->ld!=NULL)sum=rt->ld->sum,max=rt->ld->max;
    				if(rt->rd!=NULL){
    					sum+=rt->rd->sum;
    					int x=rt->rd->max;
    					if(max<x)max=x;
    				}
    				rt->sum=sum,rt->max=max;
    			}
    		}
    		void DEL(node*& rt,int l,int r){
    			if(l==r){
    				val=rt->sum;
    				delnode(rt);
    				return;
    			}
    			int mid=(l+r)>>1;
    			if(id<=mid)DEL(rt->ld,l,mid);else
    			DEL(rt->rd,mid+1,r);
    			int sum=0,max=-0x3f3f3f3f;
    			if(rt->ld!=NULL)sum=rt->ld->sum,max=rt->ld->max;
    			if(rt->rd!=NULL){
    				sum+=rt->rd->sum;
    				int x=rt->rd->max;
    				if(max<x)max=x;
    			}
    			rt->sum=sum,rt->max=max;
    		}
    		void qs(node* rt,int l,int r){
    			if(rt==NULL)return;
    			if(L<=l&&r<=R){
    				val+=rt->sum;
    				return;
    			}
    			int mid=(l+r)>>1;
    			if(L<=mid)qs(rt->ld,l,mid);
    			if(mid<R)qs(rt->rd,mid+1,r);
    		}
    		void qm(node* rt,int l,int r){
    			if(rt==NULL)return;
    			if(L<=l&&r<=R){
    				if(val<rt->max)val=rt->max;
    				return;
    			}
    			int mid=(l+r)>>1;
    			if(L<=mid)qm(rt->ld,l,mid);
    			if(mid<R)qm(rt->rd,mid+1,r);
    		}
    	public:
    		node* rt;
    		inline void init(){rt=newnode();}
    		void modify(int num,int value){
    			val=value;
    			id=num;
    			ADD(rt,1,n);
    		}
    		int deletenode(int num){
    			id=num;
    			DEL(rt,1,n);
    			return val;
    		}
    		int query_sum(int x,int y){
    			int ans=0;
    			for(;top[x]!=top[y];)
    			if(dep[top[x]]>=dep[top[y]]){
    				L=dfn[top[x]],R=dfn[x];
    				val=0;
    				qs(rt,1,n);
    				ans+=val;
    				x=fa[top[x]];
    			}else{
    				L=dfn[top[y]],R=dfn[y];
    				val=0;
    				qs(rt,1,n);
    				ans+=val;
    				y=fa[top[y]];
    			}
    			if(dep[x]<=dep[y]){
    				L=dfn[x],R=dfn[y];
    				val=0;
    				qs(rt,1,n);
    				ans+=val;
    			}else{
    				L=dfn[y],R=dfn[x];
    				val=0;
    				qs(rt,1,n);
    				ans+=val;
    			}
    			return ans;
    		}
    		int query_max(int x,int y){
    			int ans=-0x3f3f3f3f;
    			for(;top[x]!=top[y];)
    			if(dep[top[x]]>=dep[top[y]]){
    				L=dfn[top[x]],R=dfn[x];
    				val=-0x3f3f3f3f;
    				qm(rt,1,n);
    				if(val>ans)ans=val;
    				x=fa[top[x]];
    			}else{
    				L=dfn[top[y]],R=dfn[y];
    				val=-0x3f3f3f3f;
    				qm(rt,1,n);
    				if(val>ans)ans=val;
    				y=fa[top[y]];
    			}
    			if(dep[x]<=dep[y]){
    				L=dfn[x],R=dfn[y];
    				val=-0x3f3f3f3f;
    				qm(rt,1,n);
    				if(val>ans)ans=val;
    			}else{
    				L=dfn[y],R=dfn[x];
    				val=-0x3f3f3f3f;
    				qm(rt,1,n);
    				if(val>ans)ans=val;
    			}
    			return ans;
    		}
    }tree[N];
    inline int readint(){
    	int c=getchar(),d=0;
    	for(;!isdigit(c);c=getchar());
    	for(;isdigit(c);c=getchar())d=(d<<3)+(d<<1)+(c^'0');
    	return d;
    }
    struct edge{
    	int to,nxt;
    }e[N<<1];
    void dfs(int now){
    	son[now]=0;
    	sz[now]=1;
    	for(int i=head[now];i;i=e[i].nxt)
    	if(!dep[e[i].to]){
    		dep[e[i].to]=dep[now]+1;
    		fa[e[i].to]=now;
    		dfs(e[i].to);
    		sz[now]+=sz[e[i].to];
    		if(!son[now]||sz[son[now]]<sz[e[i].to])son[now]=e[i].to;
    	}
    }
    void dfs2(int now){
    	dfn[now]=++idx;
    	if(son[now])top[son[now]]=top[now],dfs2(son[now]);
    	for(int i=head[now];i;i=e[i].nxt)
    	if(dep[now]<dep[e[i].to]&&e[i].to-son[now])dfs2(top[e[i].to]=e[i].to);
    }
    inline void memory_init(){
    	for(int i=0;i<5000001;++i)
    	STK[i]=&P[i];
    	tp=5000000;
    }
    int main(){
    	memory_init();
    	for(int i=1;i<N;++i)tree[i].init();
    	n=readint(),q=readint();
    	for(int i=1;i<=n;++i)w[i]=readint(),c[i]=readint();
    	memset(head,0,sizeof head);
    	for(int i=1;i<n;++i){
    		int u=readint(),v=readint();
    		e[++cnt]=(edge){v,head[u]};
    		head[u]=cnt;
    		e[++cnt]=(edge){u,head[v]};
    		head[v]=cnt;
    	}
    	memset(dep,0,sizeof dep);
    	memset(fa,-1,sizeof fa);
    	memset(top,0,sizeof top);
    	fa[dep[1]=top[1]=1]=0;
    	dfs(1);dfs2(1);
    	for(int i=1;i<=n;++i)tree[c[i]].modify(dfn[i],w[i]);
    	while(q--){
    		scanf("%s",opt);
    		if(opt[0]=='C'){
    			if(opt[1]=='C'){
    				int x=readint(),c=readint();
    				tree[c].modify(dfn[x],tree[::c[x]].deletenode(dfn[x]));
    				::c[x]=c;
    			}else{
    				int x=readint(),w=readint();
    				tree[c[x]].modify(dfn[x],w);
    			}
    		}else{
    			if(opt[1]=='S'){
    				int x=readint(),y=readint();
    				printf("%d
    ",tree[c[x]].query_sum(x,y));
    			}else{
    				int x=readint(),y=readint();
    				printf("%d
    ",tree[c[x]].query_max(x,y));
    			}
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    Mac php使用gd库出错 Call to undefined function imagettftext()
    centos 使用 locate
    Mac HomeBrew 安装 mysql
    zsh 命令提示符 PROMPT
    新的开始
    Java 面试题分析
    Java NIO Show All Files
    正确使用 Volatile 变量
    面试题整理 2017
    有10阶梯, 每次走1,2 or 3 阶,有多少种方式???
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8696917.html
Copyright © 2011-2022 走看看