小白逛公園加強版(vijos1620)

小白逛森林公園

Description

  小新經常陪小白去公園玩,也就是所謂的遛狗啦……在小新家附近有n個公園,這些公園通過一些路徑相連,並保證每兩個公園之間有且僅有一條通路相連(也就是說這是一棵樹),小白早就看花了眼,自己也不清楚該去哪些公園玩了。 
  小白對每個公園都有一個評價(可正可負),並且它只會讓小新做兩件事:
  1. 詢問公園a到公園b路徑上最大連續公園的評價和,就是說我們把公園a到公園b路徑上的公園(包括a和b)排成一條直線,那麼小白希望知道一段連續的公園的評價和最大爲多少。
  2. 修改公園a到公園b路徑上(包括a和b)每個公園的評價值。
  小新現在已經處理不了n超過10的情況,因此請你來幫忙……

Input

第一行有一個自然數,表示n
第二行有n個自然數,表示一開始小白對每個公園的評價(評價值的絕對值不超過10000)
下面有n-1行,每行兩個數a和b,表示公園a和公園b直接由道路相連
再下面一行有一個自然數,表示m
最後m行,每行第一個數k表示要執行的操作。如果k爲1,那麼後面有兩個自然數a和b,表示詢問公園a到公園b路徑上(包含a和b)最大的連續公園評價和(如果這條路徑上每個公園的評價都爲負數,那麼最大連續和爲0)。如果k爲2,那麼後面有三個自然數a、b和c,表示把公園a到公園b路徑上所有的公園(包括a和b)的評價都修改爲c。(c的絕對值不超過10000)

Output

  對於每次詢問,輸出最大連續和。

Sample Input

5

-3 -2 1 2 3

1 2

2 3

1 4

4 5

3

1 2 5

2 3 4 2

1 2 5

Sample Output

5 9

Hint

  對於30%的數據:n,m <= 100
  對於70%的數據:n,m <= 50000
  對於100%的數據:n,m <= 100000
Solution
做了線性公園(普通版)之後就來做一下。。。
什麼都沒想,直接上了最無腦的LCT。。。
對於每一個詢問,MakeRoot之後Access,在當前Splay根節點的maxx就是答案了。
我們在更新打標記的時候,要在原有的樹上打。。。(不能一直找左兒子)。。。
估計多數人都是寫的樹剖。
標記的維護見其他人的維護數列(太懶了)

CODE

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
inline int read(){
	char c;int rec=0,f=1;
	while((c=getchar())<'0'||c>'9')if(c=='-')f=-1;
	while(c>='0'&&c<='9')rec=rec*10+c-'0',c=getchar();
	return rec*f;
}
int n,m;
struct LCT_Tree{
	int F,s[2],val,size;
	int sum,maxx,pmax[2];
	int C,R;
	inline void NewNode(int fa,int x){
		F=fa;C=R=0;size=1;
		val=sum=maxx=pmax[0]=pmax[1]=x;
		return ;
	}
}tree[100005];
inline bool Isroot(int v){return tree[tree[v].F].s[0]!=v&&tree[tree[v].F].s[1]!=v;}
inline void PMAX(int v,int f){
	tree[v].pmax[f]=max(tree[tree[v].s[f]].pmax[f],
	                tree[tree[v].s[f]].sum+tree[v].val+max(0,tree[tree[v].s[!f]].pmax[f]));
}
inline void Up(int v){
	tree[v].size=tree[tree[v].s[0]].size+1+tree[tree[v].s[1]].size;
	tree[v].sum=tree[tree[v].s[0]].sum+tree[v].val+tree[tree[v].s[1]].sum;
	tree[v].maxx=max(max(tree[tree[v].s[0]].maxx,tree[tree[v].s[1]].maxx),
	        max(0,tree[tree[v].s[0]].pmax[1])+tree[v].val+max(0,tree[tree[v].s[1]].pmax[0]));
	PMAX(v,0);PMAX(v,1);return ;
}
inline void Same(int v,int x){if(v==0)return ;
	tree[v].C=1;tree[v].val=x;tree[v].sum=x*tree[v].size;
	tree[v].maxx=tree[v].pmax[0]=tree[v].pmax[1]=max(x,tree[v].sum);
	return ;
}
inline void Rev(int v){if(v==0)return ;
	tree[v].R^=1;swap(tree[v].s[0],tree[v].s[1]);swap(tree[v].pmax[0],tree[v].pmax[1]);return ;
}
inline void Down(int v){
	if(tree[v].C){Same(tree[v].s[0],tree[v].val);Same(tree[v].s[1],tree[v].val);tree[v].C=0;}
	if(tree[v].R){Rev(tree[v].s[0]);Rev(tree[v].s[1]);tree[v].R=0;}
	return ;
}
inline void Lazy(int v){if(!Isroot(v))Lazy(tree[v].F);Down(v);return ;}
inline void Rot(int v){
    int p=tree[v].F,g=tree[p].F;
    int t1=v==tree[p].s[1],t2=p==tree[g].s[1];
    int ch=tree[v].s[1^t1];
    if(!Isroot(p))tree[g].s[t2]=v;tree[ch].F=p;
    tree[v].F=g;tree[v].s[1^t1]=p;
    tree[p].F=v;tree[p].s[t1]=ch;
    Up(p);return;
}
inline void Splay(int v){Lazy(v);
     while(!Isroot(v)){
        int p=tree[v].F,g=tree[p].F;
        if(!Isroot(p))(v==tree[p].s[1])^(p==tree[g].s[0])?Rot(v):Rot(p);
        Rot(v);
     }Up(v);return;
}
inline void Access(int v){
	for(int temp=0;v;temp=v,v=tree[v].F)
	{Splay(v);tree[v].s[1]=temp;Up(v);}
	return ;
}
inline void Make_Root(int v){Access(v);Splay(v);Rev(v);return ;}
inline void Link(int v1,int v2){Make_Root(v1);tree[v1].F=v2;return ;}
inline int Find_Root(int v){while(!Isroot(v))v=tree[v].F;return v;}
inline void Change(int v1,int v2,int x){Make_Root(v1);Access(v2);Same(Find_Root(v2),x);return ;}
inline void Ask(int v1,int v2){Make_Root(v1);Access(v2);Splay(v2);cout<<tree[v2].maxx<<' ';return ;}
int main(){
	n=read();
	for(int i=1;i<=n;i++)tree[i].NewNode(0,read());
	for(int i=1;i<n;i++)Link(read(),read());
	m=read();
	int x,y,z;
	for(int i=1;i<=m;i++){
		int f=read();
		if(f==1)Ask(read(),read());
		else {
			x=read();y=read();z=read();
			Change(x,y,z);
		}
	}cout<<'\n';
	return 0;
}

發佈了73 篇原創文章 · 獲贊 17 · 訪問量 3萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章