zoukankan      html  css  js  c++  java
  • [bzoj3999] [TJOI2015]旅游

    Description

    为了提高智商,ZJY准备去往一个新世界去旅游。这个世界的城市布局像一棵树。每两座城市之间只有一条路径可

    以互达。每座城市都有一种宝石,有一定的价格。ZJY为了赚取最高利益,她会选择从A城市买入再转手卖到B城市

    。由于ZJY买宝石时经常卖萌,因而凡是ZJY路过的城市,这座城市的宝石价格会上涨。让我们来算算ZJY旅游完之

    后能够赚取的最大利润。(如a城市宝石价格为v,则ZJY出售价格也为v)

    Input

    第一行输入一个正整数N,表示城市个数。

    接下来一行输入N个正整数表示每座城市宝石的最初价格p,每个宝石的初始价格不超过100。

    第三行开始连续输入N-1行,每行有两个数字x和y。表示x城市和y城市有一条路径。城市编号从1开始。

    下一行输入一个整数Q,表示询问次数。

    接下来Q行,每行输入三个正整数a,b,v,表示ZJY从a旅游到b,城市宝石上涨v。

    1≤ N≤50000, 1≤Q ≤50000

    Output

    对于每次询问,输出ZJY可能获得的最大利润,如果亏本则输出0。

    Sample Input

    3
    1 2 3
    1 2
    2 3
    2
    1 2 100
    1 3 100
    

    Sample Output

    1
    1
    

    Solution

    链上信息,考虑(LCT)维护(才不是因为树剖太神奇不会写呢)

    维护四个信息:区间最小值,最大值,最小收益,最大收益。

    注意这里的最小收益可以是负数,即低价买入高价卖出。

    然后最大收益分两种情况更新:左边买入右边卖出,或者在同一边买入卖出。

    注意(reverse)的时候最大收益一定是最小收益的相反数,即卖出的地方买入,买入的地方卖出,所以最大收益和最小收益取个相反数,(swap)一下就好了。

    剩下的都是板子啦~

    #include<bits/stdc++.h>
    using namespace std;
    
    #define ONLINE_JUDGE
    
    #ifdef ONLINE_JUDGE
    #define getchar() ((p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin)),p1==p2)?EOF:*p1++)
    #endif
    
    namespace fast_IO {
    	char buf[1<<21],*p1=buf,*p2=buf;
    	template <typename T> inline void read(T &x) {
    		x=0;T f=1;char ch=getchar();
    		for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-f;
    		for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0';x*=f;
    	}
    	template <typename T,typename ...Args> inline void read(T &x,Args &...args) {
    		read(x),read(args...);
    	}
    
    	char buf2[1<<21],a[100];int p,p3=-1;
    	inline void flush() {fwrite(buf2,1,p3+1,stdout),p3=-1;}
    	template <typename T> inline void write(T x) {
    		if(p3>1<<20) flush();
    		if(x<0) x=-x,buf2[++p3]='-';
    		do {a[++p]=x%10+48;} while(x/=10);
    		do {buf2[++p3]=a[p];} while(--p);
    		buf2[++p3]='
    ';
    	}
    	template <typename T,typename ...Args> inline void write(T x,Args ...args) {
    		write(x),write(args...);
    	}
    }
    
    using fast_IO :: read;
    using fast_IO :: write;
    using fast_IO :: flush;
    
    const int maxn = 2e5+10;
    
    int n,m;
    
    struct Link_Cut_Tree {
    	int fa[maxn],son[maxn][2],rev[maxn],tag[maxn],mn[maxn],mx[maxn],val[maxn],mnans[maxn],mxans[maxn];
    	void update(int x) {
    		mn[x]=mx[x]=val[x],mnans[x]=mxans[x]=0;
    		if(son[x][0]) {
    			mnans[x]=min(min(mnans[x],mnans[son[x][0]]),mn[x]-mx[son[x][0]]);
    			mxans[x]=max(max(mxans[x],mxans[son[x][0]]),mx[x]-mn[son[x][0]]);
    			mn[x]=min(mn[x],mn[son[x][0]]),mx[x]=max(mx[x],mx[son[x][0]]);
    		}
    		if(son[x][1]) {
    			mnans[x]=min(min(mnans[x],mnans[son[x][1]]),mn[son[x][1]]-mx[x]);
    			mxans[x]=max(max(mxans[x],mxans[son[x][1]]),mx[son[x][1]]-mn[x]);
    			mn[x]=min(mn[x],mn[son[x][1]]),mx[x]=max(mx[x],mx[son[x][1]]);
    		}
    	}
    	void push_rev(int x) {
    		if(!x) return ;
    		swap(son[x][0],son[x][1]),swap(mxans[x],mnans[x]);
    		rev[x]^=1,mnans[x]*=-1,mxans[x]*=-1;
    	}
    	void push_tag(int x,int v) {
    		if(x) mn[x]+=v,mx[x]+=v,tag[x]+=v,val[x]+=v;
    	}
    	void pushdown(int x) {
    		if(tag[x]) push_tag(son[x][0],tag[x]),push_tag(son[x][1],tag[x]),tag[x]=0;
    		if(rev[x]) rev[x]^=1,push_rev(son[x][0]),push_rev(son[x][1]);
    	}
    	int is_root(int x) {return son[fa[x]][0]!=x&&son[fa[x]][1]!=x;}
    	int which(int x) {return son[fa[x]][1]==x;}
    	void rotate(int x) {
    		int f=fa[x],ff=fa[f],w=which(x);
    		if(!is_root(f)) son[ff][son[ff][1]==f]=x;
    		fa[f]=x,fa[x]=ff,fa[son[x][w^1]]=f,son[f][w]=son[x][w^1],son[x][w^1]=f;
    		update(f),update(x);
    	}
    	int sta[maxn];
    	void splay(int x) {
    		int top=0,t=x;
    		while(!is_root(t)) sta[++top]=t,t=fa[t];sta[++top]=t;
    		while(top) pushdown(sta[top--]);
    		while(!is_root(x)) {
    			int y=fa[x],z=fa[y];
    			if(!is_root(y)) rotate(((son[y][1]==x)^(son[z][1]==y))?x:y);
    			rotate(x);
    		}update(x);
    	}
    	void access(int x) {
    		for(int t=0;x;t=x,x=fa[x]) splay(x),son[x][1]=t,update(x);
    	}
    	void make_root(int x) {
    		access(x),splay(x),push_rev(x);
    	}
    	void link(int x,int y) {
    		make_root(x),access(y),splay(y);fa[x]=y;
    	}
    	void modify(int x,int y,int v) {
    		make_root(x),access(y),splay(y),push_tag(y,v);
    	}
    	int query(int x,int y) {
    		make_root(x),access(y),splay(y);return max(mxans[y],0);
    	}
    }LCT;
    
    int main() {
    	read(n);for(int i=1;i<=n;i++) read(LCT.val[i]);
    	for(int i=1,x,y;i<n;i++) read(x,y),LCT.link(x,y);read(m);
    	for(int i=1,x,y,z;i<=m;i++) 
    		read(x,y,z),write(LCT.query(x,y)),LCT.modify(x,y,z);
    	flush();
    	return 0;
    }
    
    
  • 相关阅读:
    linux 环境变量
    Java finally语句到底是在return之前还是之后执行?
    JAVA NIO之浅谈内存映射文件原理与DirectMemory
    cpu架构
    tomcat 安装
    linux 下载rpm包到本地,createrepo:创建本地YUM源
    linux下查看和添加PATH环境变量
    virtualbox 相关操作
    空间叠加分析
    java程序的加载与执行
  • 原文地址:https://www.cnblogs.com/hbyer/p/10198113.html
Copyright © 2011-2022 走看看