/*
*Rainto96
*Beijing University of Posts and Telecommunications School of Software Engineering
*http://blog.csdn.net/u011775691
20万个点的树,每个点上有个点权
两种操作
1是将a到b上的所有点权改为c
2是查询a到b路径上最大连续区间和
1直接懒标记
2的话考虑维护从左到右最大和,从右到左最大和 和 最大和并维护
比较麻烦的是从a到b,合并区间的话得按照顺序,a到LCA得反转l,r,LCA到b得反转区间顺序。
*/
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <queue>
#include <cstring>
#include <string>
#include <cmath>
#include <set>
#include <map>
#include <vector>
#include <climits>
using namespace std;
#define pb push_back
#define ALL(x) x.begin(),x.end()
#define VINT vector<int>
#define PII pair<int,int>
#define MP(x,y) make_pair((x),(y))
#define ll long long
#define ull unsigned ll
#define MEM0(x) memset(x,0,sizeof(x))
#define MEM(x,val) memset((x),val,sizeof(x))
#define scan(x) scanf("%d",&(x))
#define scan2(x,y) scanf("%d%d",&(x),&(y))
#define scan3(x,y,z) scanf("%d%d%d",&(x),&(y),&(z))
#define scan4(x,y,z,k) scanf("%d%d%d%d",&(x),&(y),&(z),&(k))
#define Max(a,b) a=max(a,b)
#define Min(a,b) a=min(a,b)
using namespace std;
const int INF = 0x3f3f3f3f;///
int n,q;
const int MAXN = 200020;
int top[MAXN],fa[MAXN] , deep[MAXN] , num[MAXN] , p[MAXN] , fp[MAXN] , son[MAXN],pos , f[MAXN];
struct Edge{
int to,next;
}edge[MAXN * 2];
int head[MAXN] , tot;
void init(){
tot=0; memset(head, -1, sizeof(head));pos=0;memset(son,-1,sizeof(son));
}
void addedge(int u,int v){
edge[tot].to = v; edge[tot].next = head[u];head[u] = tot++;
}
struct Node{
int l,r,len;
int left,right,val,sum;
int lazy;
}node[MAXN*6];
#define max5(a,b,c,d,e) max(a,max(b,max(c,max(d,e))))
#define lson(x) (x)<<1
#define rson(x) (x)<<1|1
inline Node get(Node& node , Node s1, Node s2){
node.left = max(s1.sum + s2.left , s1.left);
node.right = max(s2.sum + s1.right , s2.right);
node.val = max5(node.left, node.right, s1.right + s2.left, s1.val , s2.val);
node.sum = s1.sum + s2.sum;
return node;
}
struct Seg{
void pushdown(int x){
if(node[x].lazy!=INF){
node[lson(x)].val = node[lson(x)].right = node[lson(x)].left = node[x].lazy > 0 ? node[lson(x)].len*node[x].lazy : node[x].lazy;
node[rson(x)].val = node[rson(x)].right = node[rson(x)].left = node[x].lazy > 0 ? node[rson(x)].len*node[x].lazy : node[x].lazy;
node[lson(x)].sum = node[lson(x)].len * node[x].lazy;
node[rson(x)].sum = node[rson(x)].len * node[x].lazy;
node[lson(x)].lazy = node[rson(x)].lazy = node[x].lazy;
node[x].lazy = INF;
}
}
void pushup(int x){
get(node[x], node[lson(x)], node[rson(x)]);
}
void build(int l,int r ,int x=1){
node[x].l = l , node[x].r = r;node[x].left=node[x].right=node[x].val= -INF;
node[x].len = r-l+1;
node[x].lazy=INF;
if(l==r){
node[x].sum = node[x].left = node[x].right = node[x].val = f[ fp[l] ];
return;
}
int mid = (l+r)/2;
build(l,mid,lson(x));
build(mid+1,r,rson(x));
pushup(x);
}
void update(int l,int r,int val, int x=1){
if(node[x].l>=l && node[x].r<=r){
node[x].val = node[x].left = node[x].right = val > 0?val*node[x].len : val;
node[x].sum = node[x].len * val;
node[x].lazy = val;
return;
}
int mid = (node[x].l + node[x].r)/2;
pushdown(x);
if(l <= mid) update(l,r,val,lson(x));
if(r > mid) update(l,r,val,rson(x));
pushup(x);
}
Node query(int l, int r,int x=1){
if(node[x].l>=l && node[x].r<=r){
//node[x].val = node[x].left = node[x].right = val > 0?val*node[x].len : val;
//node[x].sum = node[x].len * val;
//node[x].lazy = val;
return node[x];
}
int mid = (node[x].l + node[x].r)/2;
pushdown(x);
Node nd;bool has = false;
if(l <= mid) {
Node tmp = query(l,r,lson(x));
nd = tmp;has =true;
}
if(r > mid) {
Node tmp = query(l,r,rson(x));
if(has) get(nd,nd,tmp); else nd = tmp;
}
pushup(x);
return nd;
}
}seg;
struct TreeLink{
void build(){
dfs1(1,0,0);
getpos(1,1);
}
Node find(int u,int v){
int uid = 0;
vector<Node> vc[2];
int f1 = top[u], f2 = top[v];
while(f1 != f2){
if(deep[f1] < deep[f2]){
swap(f1,f2);swap(u,v);uid^=1;
}
Node tmp =seg.query(p[f1],p[u]);
vc[uid].pb(tmp);
u = fa[f1]; f1= top[u];
}
if(deep[u] > deep[v]) swap(u,v) , uid^=1;
vc[uid^1].pb(seg.query(p[u],p[v]));
reverse(ALL(vc[uid^1]));
for(int i=0;i<vc[uid].size();i++ ) swap(vc[uid][i].left , vc[uid][i].right);
if(vc[uid].size() == 0){
Node res = vc[uid^1][0];
for(int i=1;i<vc[uid^1].size();i++){
get(res, res, vc[uid^1][i]);
}
return res;
}else{
Node res = vc[uid][0];
for(int i=1;i<vc[uid].size();i++){
get(res, res , vc[uid][i]);
}
for(int i=0;i<vc[uid^1].size();i++){
get(res, res,vc[uid^1][i]);
}
return res;
}
}
void update(int u,int v,int val){
int f1 = top[u] , f2 = top[v];
while(f1 != f2){
if(deep[f1] < deep[f2]) swap(f1,f2),swap(u,v);
//cerr<<p[f1]<<" "<<p[u]<<" "<<val<<endl;
seg.update(p[f1],p[u],val);
u = fa[f1]; f1 = top[u];
}
if(deep[u] > deep[v]) swap(u,v);
//cerr<<p[u]<<" "<<p[v]<<" "<<val<<endl;
seg.update(p[u],p[v],val);
}
void dfs1(int u,int pre,int d){
deep[u] = d;
fa[u] = pre;
num[u] = 1;
for(int i=head[u];i!=-1;i=edge[i].next){
int v = edge[i].to;
if(v!=pre){
dfs1(v,u,d+1);
num[u] += num[v];
if(son[u] == -1 || num[v] > num[son[u]]) son[u] = v;
}
}
}
void getpos(int u,int sp){
top[u] = sp;
if(son[u] != -1) {
p[u] = pos++; fp[p[u]] = u;
getpos(son[u],sp);
}else{
p[u] = pos++;
fp[p[u]] = u;
return;
}
for(int i=head[u];i!=-1 ;i =edge[i].next){
int v= edge[i].to;
if(v != son[u] && v!=fa[u]) getpos(v,v);
}
}
}trlnk;
int e[MAXN][2];
int main(){
#ifndef ONLINE_JUDGE
//freopen("C:/OJ/in.txt","r",stdin);
#endif
while(scan2(n,q)==2){
init();
for(int i=1;i<=n;i++) scan(f[i]);
for(int i=0;i<n-1;i++){
scan2(e[i][0],e[i][1]);
//cerr<<e[i][0]<<" "<<e[i][1]<<endl;
addedge(e[i][0],e[i][1]);
addedge(e[i][1],e[i][0]);
}
trlnk.build();
//cerr<<pos-1<<" pos"<<endl;
seg.build(0,pos-1);
int kd,a,b,c;
while(q--){
scan4(kd,a,b,c);
if(kd==1){
trlnk.update(a,b,c);
}else{
int res = trlnk.find(a,b).val;
printf("%d\n",res);
}
}
}
return 0;
}
aoj2450 Do use segment tree 树链剖分
最新推荐文章于 2020-03-21 22:45:26 发布