• BZOJ2157: 旅游


    BZOJ2157: 旅游

    Description

    Ray 乐忠于旅游,这次他来到了T 城。

    T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。

    为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。

    换句话说, T 城中只有N − 1 座桥。

    Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。

    于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。

    有时,Ray 看待同一座桥的心情也会发生改变。

    现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。

    有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。

    Input

    输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0...N − 1。

    接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。

    桥的编号为1...N − 1。|w| <= 1000。

    输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。

    接下来有M 行,每行描述了一个操作,操作有如下五种形式:

    C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。

    N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。

    SUM u v,表示询问从景点u 到v 所获得的总愉悦度。

    MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。

    MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。

    测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。

    Output

    对于每一个询问(操作S、MAX 和MIN),输出答案。

    Sample Input

    3
    0 1 1
    1 2 2
    8
    SUM 0 2
    MAX 0 2
    N 0 1
    SUM 0 2
    MIN 0 2
    C 1 3
    SUM 0 2
    MAX 0 2

    Sample Output

    3
    2
    1
    -1
    5
    3

    HINT

    一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。


    题解Here!
    一道很沙茶的树剖码农题。。。
    基本操作就不讲了。。。
    注意一些标记没有清空之类的细节就好了。
    附代码:
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    #define LSON rt<<1
    #define RSON rt<<1|1
    #define DATA1(x) b[x].data1
    #define DATA2(x) b[x].data2
    #define DATA3(x) b[x].data3
    #define SIGN(x) b[x].c
    #define LSIDE(x) b[x].l
    #define RSIDE(x) b[x].r
    #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1)
    #define MAXN 100010
    #define MAX 2147483647
    using namespace std;
    int n,m,c=1,d=1;
    int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN];
    struct node1{
    	int next,to,w;
    }a[MAXN<<1];
    struct node2{
    	int data1,data2,data3,c;
    	int l,r;
    }b[MAXN<<2];
    struct node3{
    	int u,v,w;
    }g[MAXN];
    inline int read(){
    	int date=0,w=1;char c=0;
    	while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();}
    	while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();}
    	return date*w;
    }
    inline int max(const int x,const int y){return x>y?x:y;}
    inline int min(const int x,const int y){return x<y?x:y;}
    inline void add(int u,int v,int w){
    	a[c].to=v;a[c].w=w;
    	a[c].next=head[u];
    	head[u]=c++;
    	a[c].to=u;a[c].w=w;
    	a[c].next=head[v];
    	head[v]=c++;
    }
    void dfs1(int rt){
    	son[rt]=0;size[rt]=1;
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(!deep[will]){
    			deep[will]=deep[rt]+1;
    			fa[will]=rt;
    			dfs1(will);
    			size[rt]+=size[will];
    			if(size[will]>size[son[rt]])son[rt]=will;
    		}
    	}
    }
    void dfs2(int rt,int f){
    	id[rt]=d++;top[rt]=f;
    	if(son[rt])dfs2(son[rt],f);
    	for(int i=head[rt];i;i=a[i].next){
    		int will=a[i].to;
    		if(will!=fa[rt]&&will!=son[rt])
    		dfs2(will,will);
    	}
    }
    inline void pushup(int rt){
    	DATA1(rt)=DATA1(LSON)+DATA1(RSON);
    	DATA2(rt)=max(DATA2(LSON),DATA2(RSON));
    	DATA3(rt)=min(DATA3(LSON),DATA3(RSON));
    }
    inline void pushdown(int rt){
    	if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return;
    	SIGN(LSON)^=SIGN(rt);
    	DATA1(LSON)=-DATA1(LSON);DATA2(LSON)=-DATA2(LSON);DATA3(LSON)=-DATA3(LSON);
    	swap(DATA2(LSON),DATA3(LSON));
    	SIGN(RSON)^=SIGN(rt);
    	DATA1(RSON)=-DATA1(RSON);DATA2(RSON)=-DATA2(RSON);DATA3(RSON)=-DATA3(RSON);
    	swap(DATA2(RSON),DATA3(RSON));
    	SIGN(rt)=0;
    }
    void buildtree(int l,int r,int rt){
    	int mid;
    	LSIDE(rt)=l;
    	RSIDE(rt)=r;
    	if(l==r){
    		DATA1(rt)=DATA2(rt)=DATA3(rt)=0;
    		return;
    	}
    	mid=l+r>>1;
    	buildtree(l,mid,LSON);
    	buildtree(mid+1,r,RSON);
    	pushup(rt);
    }
    void update_change(int l,int r,int c,int rt){
    	int mid;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		DATA1(rt)=DATA2(rt)=DATA3(rt)=c;
    		return;
    	}
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update_change(l,r,c,LSON);
    	if(mid<r)update_change(l,r,c,RSON);
    	pushup(rt);
    }
    void update_null(int l,int r,int rt){
    	int mid;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r){
    		SIGN(rt)^=1;
    		DATA1(rt)=-DATA1(rt);DATA2(rt)=-DATA2(rt);DATA3(rt)=-DATA3(rt);
    		swap(DATA2(rt),DATA3(rt));
    		return;
    	}
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)update_null(l,r,LSON);
    	if(mid<r)update_null(l,r,RSON);
    	pushup(rt);
    }
    int query_sum(int l,int r,int rt){
    	int mid,ans=0;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
    	return DATA1(rt);
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans+=query_sum(l,r,LSON);
    	if(mid<r)ans+=query_sum(l,r,RSON);
    	return ans;
    }
    int query_max(int l,int r,int rt){
    	int mid,ans=-MAX;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
    	return DATA2(rt);
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans=max(ans,query_max(l,r,LSON));
    	if(mid<r)ans=max(ans,query_max(l,r,RSON));
    	return ans;
    }
    int query_min(int l,int r,int rt){
    	int mid,ans=MAX;
    	if(l<=LSIDE(rt)&&RSIDE(rt)<=r)
    	return DATA3(rt);
    	pushdown(rt);
    	mid=LSIDE(rt)+RSIDE(rt)>>1;
    	if(l<=mid)ans=min(ans,query_min(l,r,LSON));
    	if(mid<r)ans=min(ans,query_min(l,r,RSON));
    	return ans;
    }
    void work1(int x,int y){
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		update_null(id[top[x]],id[x],1);
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	update_null(id[x]+1,id[y],1);
    	return;
    }
    void work2(int x,int y){
    	int s=0;
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		s+=query_sum(id[top[x]],id[x],1);
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	s+=query_sum(id[x]+1,id[y],1);
    	printf("%d
    ",s);
    	return;
    }
    void work3(int x,int y){
    	int s=-MAX;
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		s=max(s,query_max(id[top[x]],id[x],1));
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	s=max(s,query_max(id[x]+1,id[y],1));
    	printf("%d
    ",s);
    	return;
    }
    void work4(int x,int y){
    	int s=MAX;
    	while(top[x]!=top[y]){
    		if(deep[top[x]]<deep[top[y]])swap(x,y);
    		s=min(s,query_min(id[top[x]],id[x],1));
    		x=fa[top[x]];
    	}
    	if(deep[x]>deep[y])swap(x,y);
    	s=min(s,query_min(id[x]+1,id[y],1));
    	printf("%d
    ",s);
    	return;
    }
    void work(){
    	char ch[10];
    	int x,y;
    	m=read();
    	while(m--){
    		scanf("%s",ch);x=read()+1;y=read()+1;
    		switch(ch[0]){
    			case 'C':{
    				x--;y--;
    				update_change(id[g[x].v],id[g[x].v],y,1);
    				break;
    			}
    			case 'N':work1(x,y);break;
    			case 'S':work2(x,y);break;
    			case 'M':{
    				if(ch[1]=='A')work3(x,y);
    				if(ch[1]=='I')work4(x,y);
    				break;
    			}
    		}
    	}
    }
    void init(){
    	n=read();
    	for(int i=1;i<n;i++){
    		g[i].u=read()+1;g[i].v=read()+1;g[i].w=read();
    		add(g[i].u,g[i].v,g[i].w);
    	}
    	deep[1]=1;
    	dfs1(1);
    	dfs2(1,1);
    	buildtree(1,n,1);
    	for(int i=1;i<n;i++){
    		if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v);
    		update_change(id[g[i].v],id[g[i].v],g[i].w,1);
    	}
    }
    int main(){
    	init();
    	work();
    	return 0;
    }
    
  • 相关阅读:
    牛客小白月赛21
    牛客小白月赛21
    CodeForces 1333-C Eugene and an array(子区间和为0、前缀和)
    页面大小、页表项、虚拟地址和物理地址之间的关系(转)
    001-Paint_FreePythonGames项目代码详解(每行都有注释!!!)
    第17讲~第19讲:函数:python的乐高积木
    第16讲:序列!序列!
    第15讲:字符串格式化
    练习23--字符串、字节和编码
    第14讲:字符串--各种奇葩内置方法
  • 原文地址:https://www.cnblogs.com/Yangrui-Blog/p/9476118.html
Copyright © 2020-2023  润新知