Aizu 2450 Do use segment tree 树链剖分+线段树

news/2025/2/26 9:46:54

Do use segment tree

Time Limit: 1 Sec  

Memory Limit: 256 MB

题目连接

http://www.bnuoj.com/v3/problem_show.php?pid=39566

Description

Given a tree with n (1 ≤ n ≤ 200,000) nodes and a list of q (1 ≤ q ≤ 100,000) queries, process the queries in order and output a value for each output query. The given tree is connected and each node on the tree has a weight wi (-10,000 ≤ wi ≤ 10,000).

Each query consists of a number ti (ti = 1, 2), which indicates the type of the query , and three numbers aibi and ci (1 ≤ ai, bi ≤ n, -10,000 ≤ ci ≤ 10,000). Depending on the query type, process one of the followings:

  • (ti = 1: modification query) Change the weights of all nodes on the shortest path between ai and bi (both inclusive) to ci.

  • (ti = 2: output query) First, create a list of weights on the shortest path between ai and bi (both inclusive) in order. After that, output the maximum sum of a non-empty continuous subsequence of the weights on the list. ci is ignored for output queries.

Input

The first line contains two integers n and q. On the second line, there are n integers which indicate w1w2, ... , wn.

Each of the following n - 1 lines consists of two integers si and ei (1 ≤ si, ei ≤ n), which means that there is an edge between si and ei.

Finally the following q lines give the list of queries, each of which contains four integers in the format described above. Queries must be processed one by one from top to bottom.

Output

For each output query, output the maximum sum in one line.

Sample Input

3 4
1 2 3
1 2
2 3
2 1 3 0
1 2 2 -4
2 1 3 0
2 2 2 0

Sample Output

6
3
-4

HINT

 

题意

给你一棵树,然后查询一条链上,区间连续最大和

然后区间更新两个操作

题解:

树链剖分+线段树

1.树链剖分 要bfs,不然会爆栈

2.如果wa了,可以尝试开ll试试

3.线段树,注意保存从左边开始的最大值,从右边开始最大值,这个区间的最大值,这个区间和

4.建议用lca写

//

代码:

#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <queue>
using namespace std;
const int maxn = 2e5 + 500;
const long long inf = 1LL << 45;
typedef pair<long long,long long>dl;
const long long check = -(1LL << 45);

typedef long long SgTreeDataType;
struct treenode
{
  int L , R  ;
  SgTreeDataType sum , Lv , Rv , setv , maxv;
  void updata(SgTreeDataType v)
  {
      setv = v ;
      sum = (R-L+1)*v;
      maxv = (v > 0) ? (R-L+1)*v : v;
    Rv = Lv = maxv;
  }
};

struct QueryData
{
    long long MaxValue , Left , Right ,sum;
    QueryData(long long MaxValue = 0,long long Left = 0,long long Right = 0,long long sum = 0) :MaxValue(MaxValue) , Left(Left) , Right(Right) , sum(sum){}
};


treenode tree[maxn * 4];

inline void push_down(int o)
{
    if(tree[o].setv == inf) return ;
    SgTreeDataType lazyval = tree[o].setv;
    tree[2*o].updata(lazyval) ; tree[2*o+1].updata(lazyval);
    tree[o].setv = inf;
}

inline void push_up(int o)
{
    tree[o].sum = tree[2*o].sum + tree[2*o+1].sum;
    tree[o].Rv = max(tree[o*2+1].Rv,tree[o*2+1].sum + tree[o*2].Rv);
    tree[o].Lv = max(tree[o*2].Lv,tree[o*2].sum + tree[o*2+1].Lv);
    tree[o].maxv = max( max(tree[o*2].maxv , tree[o*2+1].maxv) , max( tree[o*2].Rv + tree[o*2+1].Lv ,max(tree[o*2].sum + tree[o*2+1].Lv , tree[o*2+1].sum + tree[o*2].Rv)) );
}

inline void build_tree(int L , int R , int o)
{
    tree[o].L = L , tree[o].R = R,tree[o].sum = 0 , tree[o].setv = inf , tree[o].maxv = tree[o].Lv = tree[o].Rv = 0;
    if (R > L)
    {
        int mid = (L+R) >> 1;
        build_tree(L,mid,o*2);
        build_tree(mid+1,R,o*2+1);
    }
}

inline void updata(int QL,int QR,SgTreeDataType v,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) tree[o].updata(v);
    else
    {
        push_down(o);
        int mid = (L+R)>>1;
        if (QL <= mid) updata(QL,QR,v,o*2);
        if (QR >  mid) updata(QL,QR,v,o*2+1);
        push_up(o);
    }
}

inline QueryData QueryMax(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if (QL <= L && R <= QR) return QueryData(tree[o].maxv,tree[o].Lv,tree[o].Rv,tree[o].sum);
    else
    {
        int mid = (L+R)>>1;
        push_down(o);
        QueryData res;
        if(QL<=mid && QR <= mid)  res = QueryMax(QL,QR,2*o);
        else if(QL>mid&&QR>mid) res = QueryMax(QL,QR,2*o+1);
        else
        {
            QueryData Lv = QueryMax(QL,QR,2*o);
            QueryData Rv = QueryMax(QL,QR,2*o+1);
            res.MaxValue = max( max(Lv.MaxValue,Rv.MaxValue) , Lv.Right+Rv.Left );
            res.Left=Lv.Left,res.Right=Rv.Right;res.sum=Lv.sum+Rv.sum;
            res.Left=max(res.Left,Lv.sum+Rv.Left);
            res.Right=max(res.Right,Rv.sum+Lv.Right);
        }
        push_up(o);
        return res;
    }
}

inline dl QueryLeftMax(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if(QL<=L && R <= QR) return make_pair(tree[o].Lv,tree[o].sum);
    else
    {
        push_down(o);
        int mid = (L+R) >> 1;
        dl result;
        if(QL > mid) result = QueryLeftMax(QL,QR,o*2+1);
        else if(QR <= mid) result = QueryLeftMax(QL,QR,o*2);
        else
        {
            dl LL = QueryLeftMax(QL,QR,o*2);
            dl RR = QueryLeftMax(QL,QR,o*2+1);
            long long sum = LL.second + RR.second;
            long long Lval = max(LL.first , LL.second + RR.first);
            result = make_pair(Lval,sum);
        }
        push_up(o);
        return result;
    }
}

inline dl QueryRightMax(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if(QL<=L && R <= QR) return make_pair(tree[o].Rv,tree[o].sum);
    else
    {
        push_down(o);
        int mid = (L+R) >> 1;
        dl result;
        if(QL > mid) result = QueryRightMax(QL,QR,o*2+1);
        else if(QR <= mid) result = QueryRightMax(QL,QR,o*2);
        else
        {
            dl LL = QueryRightMax(QL,QR,o*2);
            dl RR = QueryRightMax(QL,QR,o*2+1);
            long long sum = LL.second + RR.second;
            long long Rval = max(RR.first , RR.second + LL.first);
            result = make_pair(Rval,sum);
        }
        push_up(o);
        return result;
    }
}


long long QuerySum(int QL,int QR,int o)
{
    int L = tree[o].L , R = tree[o].R;
    if(QL <= L && R <= QR) return tree[o].sum;
    else
    {
        int mid = (L+R) >> 1;
        long long res = 0;
        push_down(o);
        if(QL <= mid) res += QuerySum(QL,QR,2*o);
        if(QR > mid) res += QuerySum(QL,QR,2*o+1);
        push_up(o);
        return res;
    }
}




vector<int>G[maxn];
int n , q ,val[maxn] , son[maxn] , idx[maxn] , top[maxn] , deep[maxn], fa[maxn] , head[maxn],T=0;

void test()
{
    n = 10;
    build_tree( 1 , n , 1);
    for(int i = 1 ; i <= n ; ++ i) updata( i , i , i , 1);
    updata(1,1,-9999,1);
    QueryData res;
    dl BB;
    res = QueryMax(1,n,1);
    BB = QueryLeftMax(1,n,1);
    cout << res.MaxValue << endl;
    cout << BB.first << endl;
}

//********

int dfs_clock;
int que[maxn*2],num[maxn],iii[maxn],b[maxn];


void build_List()
{
    int ft = 0, rear = 0;
    que[rear++] = 1;
    fa[1] = 0;
    deep[1] = 1;
    while(ft < rear)
    {
        int u = que[ft++];
        for(int i = 0; i < G[u].size(); i++)
        {
            int v = G[u][i];
            if(v == fa[u]) continue;
            fa[v] = u;
            que[rear++] = v;
            deep[v] = deep[u]+1;
        }
    }
    memset(num, 0, sizeof (num));
    for(int i = n-1; i >= 0; i--)
    {
        int u = que[i];
        num[u]++;
        num[fa[u]] += num[u];
    }
    for(int i = 1; i <= n; i++)
    {
        for(int j = 1; j < G[i].size(); j++) if(G[i][j] != fa[i])
                if(G[i][0] == fa[i] || num[G[i][j]] > num[G[i][0]])
                    swap(G[i][0], G[i][j]);
    }
    top[1] = 1;
    for(int i = 1; i < n; i++)
    {
        int u = que[i];
        if(G[fa[u]][0] == u) top[u] = top[fa[u]];
        else top[u] = u;
    }
    memset(iii, 0, sizeof (iii));
    ft = 0;
    dfs_clock = 0;
    que[++ft] = 1;
    idx[1] = ++dfs_clock;
    b[1] = val[1];
    while(ft)
    {
        int u = que[ft];
        if(iii[u] >= G[u].size()) ft--;
        else if(G[u][iii[u]] == fa[u]) iii[u]++;
        else
        {
            int v = G[u][iii[u]];
            que[++ft] = v;
            idx[v] = ++dfs_clock;
            b[idx[v]] = val[v];
            iii[u]++;
        }
    }
    for(int i = 1 ; i <= n ; ++ i) updata(i , i , b[i] , 1);
}




//*********


void my_updata(int u , int v , int c)
{
    int f1 = top[u] , f2 = top[v];
    while(f1 != f2)
    {
        if(deep[f1] < deep[f2]) swap(f1,f2) , swap(u,v);
        updata(idx[top[u]],idx[u],c,1);
        u = top[u] , u = fa[u] , f1 = top[u];
    }
    if(deep[u] > deep[v])  swap(u,v);
    updata(idx[u] , idx[v] , c , 1);
}

long long solve(int u ,int v)
{
    int f1 = top[u] , f2 = top[v];
    if(u == v) return QueryMax(idx[u],idx[u],1).MaxValue;
    long long  s[2];s[0] = s[1] = check;
    int cur = 0;
    long long ans=check;
    while(f1 != f2)
    {
        if(deep[f1] < deep[f2]) swap(f1,f2) , swap(u,v) , cur ^= 1;
        long long sum = QuerySum(idx[top[u]],idx[u],1);
        long long tt = QueryMax(idx[top[u]],idx[u],1).MaxValue;
        ans = max(ans , tt);
        tt = QueryRightMax(idx[top[u]],idx[u],1).first;
        ans = max(ans ,tt);
        ans = max(ans ,s[cur] + tt);
        tt = QueryLeftMax(idx[top[u]],idx[u],1).first;
        s[cur] = max(sum + s[cur],tt);
        ans = max(ans , s[cur]);
        u = top[u] , u = fa[u] , f1 = top[u];
    }
    if(deep[u] > deep[v]) swap(u,v) , cur ^= 1;
    ans = max(ans , QueryMax(idx[u],idx[v],1).MaxValue);
    if(s[cur^1] != (check)) ans = max( ans , s[cur^1] + QueryRightMax(idx[u],idx[v],1).first);
    if(s[cur] != (check)) ans = max( ans , s[cur] + QueryLeftMax(idx[u],idx[v],1).first);
    if(s[cur] != (check) &&  s[cur^1] != (check)) ans = max( ans , QuerySum(idx[u],idx[v],1) + s[0] + s[1]);
    return ans;
}

inline int read()
{
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}


int main(int argc,char * argv[])
{
    scanf("%d%d",&n,&q);
    for(int i = 1 ; i <= n ; ++ i)  scanf("%d",val+i);
    for(int i = 1 ; i < n ; ++ i)
    {
        int u , v;scanf("%d%d",&u,&v);
        G[u].push_back(v);G[v].push_back(u);
    }
    build_tree(1,n,1);
    build_List();
    while(q--)
    {
        int x,y,z,w;scanf("%d%d%d%d",&x,&y,&z,&w);
        if(x == 1) my_updata(y,z,w);
        else printf("%lld\n",solve(y,z));
    }
    return 0;
}

 


http://www.niftyadmin.cn/n/1974601.html

相关文章

centos7安装k8s部署系统

centos7安装k8s部署系统 一、环境准备 标题1、设置唯一的静态ip vi /etc/sysconfig/network-scripts/ifcfg-ens33将 BOOTPROTO 改为static BOOTPROTOstatic ONBOOTyes 添加ip、网关和DNS地址&#xff0c;网关可以通过命令&#xff1a;“netstat -rn” 查看 IPADDR192.168.2…

Hibernate 5.0.2加载hibernate.cfg.xml时mapping不生效

2019独角兽企业重金招聘Python工程师标准>>> //Group类 package com.jingtai;public class Group {private int groupId;private String groupName;public void setGroupId(int id){groupId id;}public int getGroupId(){return groupId;}public void setGroupName…

k8s运行minio的yml文件

k8s运行minio的yml文件 apiVersion: apps/v1 kind: Deployment metadata:labels:app: minioname: minionamespace: default spec:replicas: 1selector:matchLabels:app: miniotemplate:metadata:labels:app: miniospec:containers:- args:- server- /data- --console-address-…

端口详解2

5050|多媒体会议控制协议5051|ITA代理5052|ITA管理5137|MyCTS服务器端口5150|Ascend通道管理协议5154|BZFlag游戏服务器5190|America-Online(美国在线)5191|AmericaOnline1(美国在线)5192|AmericaOnline2(美国在线)5193|AmericaOnline3(美国在线)5222|Jabber客户端连接5225|HP(…

虚拟机中Linux系统安装

虚拟机安装完成后就应安装虚拟机了,首先要先有虚拟机的镜像安装文件,可以去搜索下载 打开虚拟机界面创建新的虚拟机 默认典型安装点击下一步 浏览中选择要安装的系统镜像文件,点击下一步安装 定义要安装的虚拟机的作用最为名字,安装位置也是自定义的,我这里装在了专用盘D中…

【数据库】MFC ODBC(四)

7、滚动记录 CRecordset提供了几个成员函数用来在记录集中滚动。当用这些函数滚动到一个新记录时&#xff0c;框架会自动地把新记录的内容拷贝到域数据成员中。 void MoveNext( ); //前进一个记录 void MovePrev( ); //后退一个记录 void MoveFirst( ); //滚动到记录集中的第…

【Vue3】学习笔记-toRaw 与 markRaw

toRaw&#xff1a; 作用&#xff1a;将一个由reactive生成的响应式对象转为普通对象。使用场景&#xff1a;用于读取响应式对象对应的普通对象&#xff0c;对这个普通对象的所有操作&#xff0c;不会引起页面更新。 markRaw&#xff1a; 作用&#xff1a;标记一个对象&#xff…

故事一

最近学习状态不是很好,看到一篇关于量子计算机原理的文章,现在贴出来让大家看看(侵权删除) 电影《三体》上映后的某一天&#xff0c; 三体人突然降临。 它们用飞船把地球团团围住&#xff0c; 监视了地球向宇宙发射的所有信息。 地球人通过面壁计划&#xff0c; 选出了一位物理…