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
- Do use segment tree 树链剖分,按顺序剖分
- Aoj 2450 Do use segment tree【树链剖分】
- aoj2450 Do use segment tree 树链剖分
- Aizu 2450 Do use segment tree (树链剖分)
- bnuoj 39566 Do use segment tree(树链剖分)
- Aizu 2450 Do use segment tree LCT
- 树链剖分 JAG Summer 2012 Day 4 D Do use segment tree
- BNUOJ 39566 Do use segment tree(树链剖分——点权)
- AOJ 2450 Do use segment tree (树链剖分 + 线段树区间合并)
- BNUOJ39566 Do use segment tree (树链剖分+维护区间最大连续和)
- Segment tree
- Segment Tree
- Segment Tree
- segment Tree
- Segment Tree
- Segment Tree
- POJ 3237 Tree 树链剖分(路径剖分
- 线段树(segment tree)
- Android decode
- JAVA+jni 包名或方法名中含有下划线(_)的解决方法
- 删除分区表students子分区sex_male中年龄大于30岁的记录
- cocos2dx2.2 mac下创建工程命令
- hdu 5493 Queue(线段树)
- Do use segment tree 树链剖分,按顺序剖分
- 欢迎使用CSDN-markdown编辑器
- 1004. Counting Leaves (30)
- 微博剩余字数输入统计
- ocp-50
- 关于BIOS的入口地址0xFFFF0
- Embedded Development Daily Study
- 分享电信ifree黄金版
- base64编解码