• BZOJ3531 [Sdoi2014]旅行 树链剖分 线段树


    原文链接:http://www.cnblogs.com/zhouzhendong/p/8080189.html


    题目传送门 - BZOJ3531


    题意概括

      一棵树,n个节点,每一个节点两个值,一个颜色,一个权值。

      4种操作:

      1. 修改某一个节点的颜色

      2. 修改某一个节点的权值

      3. 查询两点之间某一颜色的节点最大权值

      4. 查询两点之间某一颜色的节点权值和


    题解

      首先闭着眼睛写上树链剖分。

      因为题目里面说了,颜色的值<=100000。

      所以我们马上想到的开100000个线段树。

      那么修改什么的都是log2n的,时间没问题了。

      那么空间显然要炸。

      怎么做——动态开点啊。

      操作涉及的点很少,所以空间复杂度也是(q+n) log n

      然后就水过了、


    代码

    #include <cstring>
    #include <cstdio>
    #include <algorithm>
    #include <cstdlib>
    #include <cmath>
    using namespace std;
    const int N=100005,S=N*2*20;
    bool isd(char ch){return '0'<=ch&&ch<='9';}
    int read(){
    	int res=0;
    	char ch=getchar();
    	while (!isd(ch))
    		ch=getchar();
    	while (isd(ch))
    		res=res*10+ch-48,ch=getchar();
    	return res;
    }
    struct Gragh{
    	int cnt,y[N*2],nxt[N*2],fst[N];
    	void clear(){
    		cnt=0;
    		memset(fst,0,sizeof fst);
    	}
    	void add(int a,int b){
    		y[++cnt]=b,nxt[cnt]=fst[a],fst[a]=cnt;
    	}
    }g;
    int n,q,root[N],w[N],c[N];
    int fa[N],son[N],size[N],depth[N],top[N],p[N],ap[N],cnp=0;
    int ls[S],rs[S],Max[S],sum[S],tot=0;
    void Get_Gen_Info(int rt,int pre,int d){
    	size[rt]=1,fa[rt]=pre,son[rt]=-1,depth[rt]=d;
    	for (int i=g.fst[rt];i;i=g.nxt[i])
    		if (g.y[i]!=pre){
    			int s=g.y[i];
    			Get_Gen_Info(s,rt,d+1);
    			size[rt]+=size[s];
    			if (son[rt]==-1||size[s]>size[son[rt]])
    				son[rt]=s;
    		}
    }
    void Get_Top(int rt,int tp){
    	top[rt]=tp;
    	ap[p[rt]=++cnp]=rt;
    	if (son[rt]==-1)
    		return;
    	Get_Top(son[rt],tp);
    	for (int i=g.fst[rt];i;i=g.nxt[i]){
    		int s=g.y[i];
    		if (s!=fa[rt]&&s!=son[rt])
    			Get_Top(s,s);
    	}
    }
    void pushup(int rt){
    	Max[rt]=max(Max[ls[rt]],Max[rs[rt]]);
    	sum[rt]=sum[ls[rt]]+sum[rs[rt]];
    }
    void change(int &rt,int L,int R,int pos,int v){
    	if (!rt)
    		rt=++tot;
    	if (L==R){
    		Max[rt]=sum[rt]=v;
    		return;
    	}
    	int mid=(L+R)>>1;
    	if (pos<=mid)
    		change(ls[rt],L,mid,pos,v);
    	else
    		change(rs[rt],mid+1,R,pos,v);
    	pushup(rt);
    }
    int query(int rt,int L,int R,int xL,int xR,int op){
    	if (!rt||R<xL||L>xR)
    		return 0;
    	if (xL<=L&&R<=xR)
    		return op?Max[rt]:sum[rt];
    	int mid=(L+R)>>1;
    	int ansL=query(ls[rt],L,mid,xL,xR,op);
    	int ansR=query(rs[rt],mid+1,R,xL,xR,op);
    	return op?max(ansL,ansR):(ansL+ansR);
    }
    int Tquery(int a,int b,int op){
    	int f1=top[a],f2=top[b],color=c[a],ans=0;
    	while (f1!=f2){
    		if (depth[f1]<depth[f2])
    			swap(f1,f2),swap(a,b);
    		int v=query(root[color],1,n,p[f1],p[a],op);
    		ans=op?max(ans,v):(ans+v);
    		a=fa[f1],f1=top[a];
    	}
    	if (depth[a]>depth[b])
    		swap(a,b);
    	int v=query(root[color],1,n,p[a],p[b],op);
    	ans=op?max(ans,v):(ans+v);
    	return ans;
    }
    int main(){
    	n=read(),q=read();
    	for (int i=1;i<=n;i++)
    		w[i]=read(),c[i]=read();
    	g.clear();
    	for (int i=1,a,b;i<n;i++){
    		a=read(),b=read();
    		g.add(a,b);
    		g.add(b,a);
    	}
    	Get_Gen_Info(1,0,0);
    	Get_Top(1,1);
    	for (int i=1;i<=n;i++)
    		change(root[c[i]],1,n,p[i],w[i]);
    	for (int i=1;i<=q;i++){
    		char op[5];
    		int x,y;
    		scanf("%s",op);
    		x=read(),y=read();
    		if (op[0]=='C'&&op[1]=='C'){
    			change(root[c[x]],1,n,p[x],0);
    			change(root[c[x]=y],1,n,p[x],w[x]);
    		}
    		if (op[0]=='C'&&op[1]=='W')
    			change(root[c[x]],1,n,p[x],w[x]=y);
    		if (op[0]=='Q'&&op[1]=='S')
    			printf("%d
    ",Tquery(x,y,0));
    		if (op[0]=='Q'&&op[1]=='M')
    			printf("%d
    ",Tquery(x,y,1));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    -1%256的值是多少?
    Glut,程序的基本架构
    剑指offer:数值的整数次方
    剑指offer:二进制中1的个数
    剑指offer:斐波那契数列的应用
    剑指offer:斐波那契数列
    剑指offer:旋转数组中的最小数字
    弱智的grub消除法
    POJ 3126 Prime Path
    HDU 1426 Sudoku Killer
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3531.html
Copyright © 2020-2023  润新知