aoj2450 Do use segment tree 树链剖分

/*
*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;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值