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;
    }
    
  • 相关阅读:
    SDNU 1311.Binomial Coeffcients
    SDNU 1306.兑数
    SDNU 1272.SL的秘密
    SDNU 1270.超超的难题
    XCode 自动化打包总结
    Xrun 将 app 转化为 IPA
    mac终端下运行shell脚本
    ios 检测应用程序升级问题
    在iis6.0公布asp.net mvc3网站
    IOS 中 NSArray
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8696917.html
Copyright © 2011-2022 走看看