Do use segment tree 树链剖分,按顺序剖分

来源:互联网 发布:lsd可以在淘宝上买到 编辑:程序博客网 时间:2024/05/01 10:40

一棵树,支持两种操作,1是将a到b路径上点的权值改为c,求a到b路径上的最大连续字段和。

维护最大字段和,最大前缀和,最大后缀和。

树练剖分,需要按顺序求出链的所有段,向上合并。

#include<iostream>#include<cstring>#include<cstdio>#include<ostream>#include<istream>#include<algorithm>#include<queue>#include<string>#include<cmath>#include<set>#include<bitset>#include<map>#include<stack>#include<vector>#define fi first#define se second#define ll long long#define pii pair<int,int>#define inf (1<<30)#define eps 1e-8#define pb push_backusing namespace std;const int maxn=200005;int son[maxn],top[maxn],dep[maxn],fa[maxn],siz[maxn],id[maxn],fid[maxn];int sz;vector<int>g[maxn];int val[maxn];int n,q;struct Node{    ll ls,rs,sum,ans;    Node(ll a,ll b,ll c,ll d):ls(a),rs(b),sum(c),ans(d){}    Node(){}}node[maxn<<2];ll add[maxn<<2];void dfs(int u,int f){    siz[u]=1;    son[u]=0;    for(int i=0;i<g[u].size();i++) {        if(g[u][i]==f)            continue;        int v=g[u][i];        fa[v]=u;        dep[v]=dep[u]+1;        dfs(v,u);        if(siz[v]>siz[son[u]]) son[u]=v;        siz[u]+=siz[v];    }}void build(int u,int w){    id[u]=++sz;    fid[sz]=u;    top[u]=w;    if(son[u]) build(son[u],w);    for(int i=0;i<g[u].size();i++) {        int v=g[u][i];        if(v==fa[u]) continue;        if(v!=son[u]) build(v,v);    }}void T(){    int rt=(n+1)/2;    sz=0;    dep[rt]=0;    fa[rt]=0;    dfs(rt,0);    build(rt,rt);}void pushUp(int rt){    node[rt].ans=max(node[rt<<1].ans,node[rt<<1|1].ans);    node[rt].ans=max(node[rt].ans,node[rt<<1].rs+node[rt<<1|1].ls);    node[rt].sum=node[rt<<1].sum+node[rt<<1|1].sum;    node[rt].ls=max(node[rt<<1].ls,node[rt<<1].sum+node[rt<<1|1].ls);    node[rt].rs=max(node[rt<<1|1].rs,node[rt<<1|1].sum+node[rt<<1].rs);}void change(int l,int r,int rt,int c){    if(c>=0) {        node[rt].sum=(ll)(r-l+1)*c;        node[rt].ans=node[rt].ls=node[rt].rs=node[rt].sum;    }    else {        node[rt].sum=(ll)(r-l+1)*c;        node[rt].ls=node[rt].rs=node[rt].ans=c;    }}void pushDown(int l,int r,int rt){    if(add[rt]==inf) return;    int m=((l+r)>>1);    change(l,m,rt<<1,add[rt]);    change(m+1,r,rt<<1|1,add[rt]);    add[rt<<1]=add[rt<<1|1]=add[rt];    add[rt]=inf;}Node unite(Node u,Node v){    Node p;    p.ans=max(u.ans,v.ans);    p.ans=max(p.ans,u.rs+v.ls);    p.sum=u.sum+v.sum;    p.ls=max(u.ls,u.sum+v.ls);    p.rs=max(v.rs,v.sum+u.rs);    return p;}Node query(int L,int R,int l,int r,int rt){    if(L<=l&&R>=r)        return node[rt];    pushDown(l,r,rt);    Node ans=Node(-inf, -inf, 0, -inf);    int m=((l+r)>>1);    if(L<=m)        ans=unite(ans,query(L,R,l,m,rt<<1));    if(R>m)        ans=unite(ans,query(L,R,m+1,r,rt<<1|1));    return ans;}ll query(int u,int v){    int a = top[u], b = top[v];    Node lpath = Node(-inf , -inf, 0, -inf), rpath = Node(-inf, -inf, 0, -inf);    while(a != b){        if( dep[a] > dep[b]){            Node res = query(id[a], id[u],1,n,1);            swap(res.ls, res.rs);            lpath = unite(lpath, res);            u = fa[a];            a = top[u];        }        else{            Node res = query(id[b], id[v],1,n,1);            rpath = unite(res, rpath);            v = fa[b];            b = top[v];        }    }    Node ans;    if( dep[u] < dep[v] ){        ans = query(id[u], id[v],1,n,1);    }    else{        ans = query(id[v], id[u],1,n,1);        swap(ans.ls,ans.rs);    }    ans = unite(lpath, ans);    ans = unite(ans, rpath);    return ans.ans;}void update(int L,int R,int c,int l,int r,int rt){    if(L<=l&&R>=r) {        change(l,r,rt,c);        add[rt]=c;        return;    }    pushDown(l,r,rt);    int m=((l+r)>>1);    if(L<=m)        update(L,R,c,l,m,rt<<1);    if(R>m)        update(L,R,c,m+1,r,rt<<1|1);    pushUp(rt);}void update(int a,int b,int c){    int f1=top[a],f2=top[b];    while(f1!=f2) {        if(dep[f1]<dep[f2]) {            swap(f1,f2);            swap(a,b);        }        update(id[f1],id[a],c,1,n,1);        a=fa[f1]; f1=top[a];    }    if(dep[a]>dep[b]) swap(a,b);    update(id[a],id[b],c,1,n,1);}void buildTree(int l,int r,int rt){    add[rt]=inf;    if(l==r) {        int a=fid[l];        node[rt].ls=node[rt].rs=node[rt].sum=node[rt].ans=val[a];        return;    }    int m=((l+r)>>1);    buildTree(l,m,rt<<1);    buildTree(m+1,r,rt<<1|1);    pushUp(rt);}int main(){    int ty;    int a,b,c;    while(~scanf("%d%d",&n,&q)) {        for(int i=1;i<=n;i++) {            scanf("%d",&val[i]);            g[i].clear();        }        for(int i=0;i<n-1;i++) {            scanf("%d%d",&a,&b);            g[a].push_back(b);            g[b].push_back(a);        }        T();        buildTree(1,n,1);        for(int i=0;i<q;i++) {            scanf("%d%d%d%d",&ty,&a,&b,&c);            if(ty==1) {                update(a,b,c);            }            else {                printf("%lld\n",query(a,b));            }        }    }    return 0;}


0 0