水题,只是坑点多,\(tag\)为\(0\)时可能也要\(pushdown\),所以要\(bool\)标记是否需要。最后树链剖分询问时注意线段有向!!!

#include <cstring>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iostream>
#include <numeric>
#define R(a,b,c) for(register int a = (b); a <= (c); ++a)
#define nR(a,b,c) for(register int a = (b); a >= (c); --a)
#define Swap(a,b) ((a) ^= (b) ^= (a) ^= (b))
#define MP make_pair
#ifdef QWQ
#define D_e_Line printf("\n------\n")
#define D_e(x) cerr << (#x) << " " << x << endl
#define C_e(x) cout << (#x) << " " << x << endl
#define FileOpen() freopen("in.txt", "r", stdin)
#define FileSave() freopen("out.txt", "w", stdout)
#define Pause() system("pause")
#include <cassert>
#define PASS fprintf(stderr, "Passing [%s] in LINE %d\n",__FUNCTION__,__LINE__)
#else
#define D_e_Line
#define D_e(x)
#define C_e(x)
#define FileOpen()
#define FileSave()
#define Pause()
#define PASS
#endif
using namespace std;
struct FastIO {
template<typename ATP> inline FastIO& operator >> (ATP &x) {
x = 0; int sign = 1; char c;
for(c = getchar(); c < '0' || c > '9'; c = getchar()) if(c == '-') sign = -1;
while(c >= '0' && c <= '9') x = x * 10 + (c ^ '0'), c = getchar();
if(sign == -1) x = -x;
return *this;
}
} io;
template<typename ATP> inline ATP Max(ATP x, ATP y) {
return x > y ? x : y;
}
template<typename ATP> inline ATP Min(ATP x, ATP y) {
return x < y ? x : y;
}
template<typename ATP> inline ATP Abs(ATP x) {
return x < 0 ? -x : x;
}
#include <vector>
const int N = 2e5 + 7;
struct Edge {
int nxt, pre;
} e[N << 1];
int head[N], cntEdge;
inline void add(int u, int v) {
e[++cntEdge] = (Edge){ head[u], v}, head[u] = cntEdge;
}
int fa[N], son[N], siz[N], dep[N], dfn[N], dfnIdx, top[N], rnk[N], val[N], n;
void DFS_First(int u, int father) {
dep[u] = dep[father] + 1, fa[u] = father, siz[u] = 1;
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v == father) continue;
DFS_First(v, u);
siz[u] += siz[v];
if(siz[v] > siz[son[u]]) son[u] = v;
}
}
void DFS_Second(int u, int Tp) {
top[u] = Tp, dfn[u] = ++dfnIdx, rnk[dfnIdx] = u;
if(!son[u]) return;
DFS_Second(son[u], Tp);
for(register int i = head[u]; i; i = e[i].nxt){
int v = e[i].pre;
if(v != fa[u] && v != son[u]) DFS_Second(v, v);
}
}
struct Seg {
int sum, val, pre, suf, tag;
bool flag;
Seg() {sum = val = pre = suf = tag = flag = 0;}
Seg operator + (const Seg &b) const {
Seg c;
c.sum = sum + b.sum;
c.val = Max(Max(val, b.val), suf + b.pre);
c.pre = Max(pre, sum + b.pre);
c.suf = Max(b.suf, b.sum + suf);
return c;
}
} t[N << 2];
#define ls rt << 1
#define rs rt << 1 | 1
#define lson rt << 1, l, mid
#define rson rt << 1 | 1, mid + 1, r
inline void Pushup(int &rt) {
t[rt] = t[ls] + t[rs];
}
inline void Pushdown(int &rt, int l, int mid, int r) {
t[ls].sum = (mid - l + 1) * t[rt].tag;
t[rs].sum = (r - mid) * t[rt].tag;
t[ls].pre = t[ls].val = t[ls].suf = Max(t[ls].sum, 0);
t[rs].pre = t[rs].val = t[rs].suf = Max(t[rs].sum, 0);
t[ls].flag = t[rs].flag = true;
t[ls].tag = t[rs].tag = t[rt].tag;
t[rt].tag = 0;
t[rt].flag = false;
}
void Build(int rt, int l, int r) {
if(l == r){
t[rt].sum = val[rnk[l]];
t[rt].val = t[rt].pre = t[rt].suf = Max(t[rt].sum, 0);
return;
}
int mid = (l + r) >> 1;
Build(lson), Build(rson);
Pushup(rt);
}
void Updata(int rt, int l, int r, int L, int R, int w) {
if(L <= l && r <= R){
t[rt].sum = (r - l + 1) * w;
t[rt].pre = t[rt].suf = t[rt].val = Max(t[rt].sum, 0);
t[rt].tag = w;
t[rt].flag = true;
return;
}
int mid = (l + r) >> 1;
if(t[rt].flag) Pushdown(rt, l, mid, r);
if(L <= mid) Updata(lson, L, R, w);
if(R > mid) Updata(rson, L, R, w);
Pushup(rt);
}
Seg Query(int rt, int l, int r, int L, int R) {
if(L <= l && r <= R) return t[rt];
int mid = (l + r) >> 1;
if(t[rt].flag) Pushdown(rt, l, mid, r);
Seg s;
if(L <= mid) s = Query(lson, L, R);
if(R > mid) s = s + Query(rson, L, R);
return s;
}
inline void Updata(int x, int y, int w) {
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]) Swap(x, y);
Updata(1, 1, n, dfn[top[x]], dfn[x], w);
x = fa[top[x]];
}
if(dep[x] < dep[y]) Swap(x, y);
Updata(1, 1, n, dfn[y], dfn[x], w);
}
//inline int Query(int x, int y) {
// Seg s;
// while(top[x] != top[y]){
// if(dep[top[x]] < dep[top[y]]) Swap(x, y);
// s = s + Query(1, 1, n, dfn[top[x]], dfn[x]);
// x = fa[top[x]];
// }
// if(dep[x] < dep[y]) Swap(x, y);
// Swap(s.suf, s.pre);
// return (s + Query(1, 1, n, dfn[y], dfn[x])).val;
//}
inline int Query(int x, int y) {
Seg L, R;
while(top[x] != top[y]){
if(dep[top[x]] < dep[top[y]]){
R = Query(1, 1, n, dfn[top[y]], dfn[y]) + R;
y = fa[top[y]];
}
else{
L = Query(1, 1, n, dfn[top[x]], dfn[x]) + L;
x = fa[top[x]];
}
}
if(dep[x] > dep[y]){
L = Query(1, 1, n, dfn[y], dfn[x]) + L;
}
else{
R = Query(1, 1, n, dfn[x], dfn[y]) + R;
}
Swap(L.pre, L.suf);
return (L + R).val;
}
int main() {
//FileOpen();
//FileSave();
io >> n;
R(i,1,n) io >> val[i];
R(i,2,n){
int u, v;
io >> u >> v;
add(u, v);
add(v, u);
}
DFS_First(1, 0);
DFS_Second(1, 1);
Build(1, 1, n);
int m;
io >> m;
while(m--){
int opt, l, r, w;
io >> opt >> l >> r;
if(opt == 1){
printf("%d\n", Query(l, r));
}
else{
io >> w;
Updata(l, r, w);
}
} return 0;
}
/*
13
9 4 12 18 19 1 11 18 16 5 1 10 9 2 1
3 1
4 1
5 1
6 4
7 3
8 3
9 3
10 8
11 9
12 10
13 10
5
2 1 10 10
2 7 13 6
1 5 9
1 4 10
1 9 10
*/

SP6779 GSS7 - Can you answer these queries VII(线段树,树链剖分)的更多相关文章

  1. SP6779 GSS7 - Can you answer these queries VII

    纯数据结构题,没有思维难度.直接用线段树求最大子段和的方法完成树上路径的合并.注意链上合并顺序要符合序列的前后顺序. #include <cstdio> #include <cstr ...

  2. 题解 SP6779 【GSS7 - Can you answer these queries VII】

    题目传送门 题目大意 给出一个\(n\)个点的树,每个点有权值.有\(m\)次操作,每次要么查询一条链上的最大子段和,要么把一条链的权值都修改为一个常数. \(n,m\le 10^5\) 思路 如果是 ...

  3. SPOJ GSS7 - Can you answer these queries VII

    板的不能再板,链剖+线段树或者是LCT随便维护. 感觉唯一要注意的是跳链的时候要对$x$向上跳和$y$向上跳的情况分开讨论,而不能直接$swap$,因为只有两段接触的端点才能相互合并,而且每一次向上跳 ...

  4. SPOJ GSS7 Can you answer these queries VII ——树链剖分 线段树

    [题目分析] 问题放到了树上,直接链剖+线段树搞一搞. 调了300行+. (还是码力不够) [代码] #include <cstdio> #include <cstring> ...

  5. GSS7 spoj 6779. Can you answer these queries VII 树链剖分+线段树

    GSS7Can you answer these queries VII 给出一棵树,树的节点有权值,有两种操作: 1.询问节点x,y的路径上最大子段和,可以为空 2.把节点x,y的路径上所有节点的权 ...

  6. GSS4 2713. Can you answer these queries IV 线段树

    GSS7 Can you answer these queries IV 题目:给出一个数列,原数列和值不超过1e18,有两种操作: 0 x y:修改区间[x,y]所有数开方后向下调整至最近的整数 1 ...

  7. SPOJ GSS1_Can you answer these queries I(线段树区间合并)

    SPOJ GSS1_Can you answer these queries I(线段树区间合并) 标签(空格分隔): 线段树区间合并 题目链接 GSS1 - Can you answer these ...

  8. 6779. Can you answer these queries VII - SPOJ

    Given a tree with N ( N<=100000 ) nodes. Each node has a interger value x_i ( |x_i|<=10000 ). ...

  9. SPOJ GSS3 Can you answer these queries III[线段树]

    SPOJ - GSS3 Can you answer these queries III Description You are given a sequence A of N (N <= 50 ...

随机推荐

  1. uniapp设置竖屏

    //在APP.vue中的onLaunch钩子写入plus.screen.lockOrientation('portrait-primary');

  2. drools执行完某个规则后终止别的规则执行

    目录 1.背景 2.需求 3.实现方案 1.通过Fact判断 2.通过全局变量判断 3.通过halt方法 4.实现上述需求 4.1 drl 文件编写 4.2 运行结果 5.完整代码 1.背景 在我们开 ...

  3. 第6组 Beta冲刺 总结

    目录 1. 基本情况 2. 思考与总结 2.1. 设想和目标 2. 计划 3. 资源 4. 变更管理 5. 设计/实现 6. 测试/发布 7. 团队的角色,管理,合作 8. 总结 3. 敏捷开发 1. ...

  4. MySQL - 分页问题

    MySQL中的分页 MySQL中通过LIMIT关键字可以实现分页,如:(其中0表示开始记录数,10表示返回数据的数量) SELETE * FROM table_name LIMIT 0, 10 MyB ...

  5. c++ 超长整数乘法 高精度乘法

    c++ 超长整数乘法 高精度乘法 解题思路 参考加法和减法解题思路 乘法不是一位一位的按照手算的方式进行计算,而是用循环用一个数的某一位去乘另外一个数 打卡代码 #include<bits/st ...

  6. XMAL中的x是何方神僧

    在一开始我们接触WPF时,总是被小X牵着鼻子走,还不知道它是谁,比如 <Window x:Class="Blend_WPF.WindowStyle"        xmlns ...

  7. 配置nginx多域名虚拟主机

    1.先做域名映射,由于我们使用的是阿里云域名. 登录阿里云控制台-->域名与网站(万网)-->域名-->选择一个域名-->域名解析-->添加记录 配置静态资源下载转发: ...

  8. ArrayList和LinkedList内部是怎么实现的?他们之间的区别和优缺点?

    ArrayList 内部使用了数组形式进行了存储,利用数组的下标进行元素的访问,因此对元素的随机访问速度非常快.因为是数组,所以ArrayList在初始化的时候, 有初始大小10,插入新元素的时候,会 ...

  9. Python音频处理基础知识,这不是轻轻松松~~~

    大家好鸭,我是小熊猫 咱今天来讲一讲音频处理的基础知识上才艺~~~ 1.声音的基础 2.python读取.wav音频 欢迎加入白嫖Q群:660193417### import wave import ...

  10. easyexcel注解

    1.@ExcelProperty 必要的一个注解,注解中有三个参数value,index分别代表列明,列序号 1.value 通过标题文本对应2.index 通过文本行号对应 2.@ColumnWit ...