首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >洛谷P4719 【模板】动态dp(ddp LCT)

洛谷P4719 【模板】动态dp(ddp LCT)

作者头像
attack
发布于 2019-03-08 01:49:37
发布于 2019-03-08 01:49:37
38300
代码可运行
举报
运行总次数:0
代码可运行

题意

题目链接

Sol

动态dp板子题。有些细节还没搞懂,待我研究明白后再补题解。。。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#include<bits/stdc++.h>
#define LL long long 
using namespace std;
const int MAXN = 1e5 + 10, INF = INT_MAX;
template<typename A, typename B> inline bool chmax(A &x, B y) {
    return x < y ? x = y, 1 : 0;
}
inline int read() {
    char c = getchar(); int x = 0, f = 1;
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();}
    while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar();
    return x * f;
}
int N, M, a[MAXN], f[MAXN][2];
struct Ma {
    LL m[3][3];
    Ma() {
        memset(m, -0x3f, sizeof(m));
    }
    Ma operator * (const Ma &rhs) const {
        Ma ans;
        for(int i = 1; i <= 2; i++)
            for(int j = 1; j <= 2; j++)
                for(int k = 1; k <= 2; k++)
                    chmax(ans.m[i][j], m[i][k] + rhs.m[k][j]);
        return ans;
    }
}val[MAXN], sum[MAXN];
vector<int> v[MAXN];
int ch[MAXN][2], fa[MAXN];
#define ls(x) ch[x][0]
#define rs(x) ch[x][1]
void update(int k) {
    sum[k] = val[k];
    if(rs(k)) sum[k] = sum[k] * sum[rs(k)];
    if(ls(k)) sum[k] = sum[ls(k)] * sum[k];
}
bool ident(int x) {
    return rs(fa[x]) == x;
}
bool isroot(int x) {
    return ls(fa[x]) != x && rs(fa[x]) != x;
}
void connect(int x, int _fa, int tag) {
    fa[x] = _fa;
    ch[_fa][tag] = x;
}
void rotate(int x) {
    int y = fa[x], r = fa[y], yson = ident(x), rson = ident(y);
    int b = ch[x][yson ^ 1];
    fa[x] = r;
    if(!isroot(y)) connect(x, r, rson);
    connect(b, y, yson);
    connect(y, x, yson ^ 1);
    update(y); update(x);
}
void splay(int x) {
    for(int y = fa[x]; !isroot(x); rotate(x), y = fa[x])
        if(!isroot(y))
            rotate(ident(y) == ident(x) ? y : x);
}
void access(int x) {
    for(int y = 0; x; x = fa[y = x]) {
        splay(x);
        if(rs(x)) {
            val[x].m[1][1] += max(sum[rs(x)].m[1][1], sum[rs(x)].m[2][1]);
            val[x].m[2][1] += sum[rs(x)].m[1][1];
        }
        if(y) {
            val[x].m[1][1] -= max(sum[y].m[1][1], sum[y].m[2][1]);
            val[x].m[2][1] -= sum[y].m[1][1];
        }
        val[x].m[1][2] = val[x].m[1][1];
        rs(x) = y;
        update(x);
    }
}
int Modify(int p, int v) {
    access(p); splay(p);
    val[p].m[2][1] -= a[p] - v; 
    update(p);
    a[p] = v;
    splay(1);
    return max(sum[1].m[1][1], sum[1].m[2][1]);
}
void dfs(int x, int _fa) {
    fa[x] = _fa;
    f[x][1] = a[x];
    for(auto &to : v[x]) {
        if(to == _fa) continue;
        dfs(to, x);
        f[x][0] += max(f[to][0], f[to][1]);
        f[x][1] += f[to][0];
    }
    val[x].m[1][1] = f[x][0]; val[x].m[1][2] = f[x][0];
    val[x].m[2][1] = f[x][1]; val[x].m[2][2] = -INF;
    update(x);
//  sum[x] = val[x];
}
int main() {
    //freopen("a.in", "r", stdin);
    N = read(); M = read();
    for(int i = 1; i <= N; i++) a[i] = read();
    for(int i = 1; i < N; i++) {
        int x = read(), y = read();
        v[x].push_back(y);
        v[y].push_back(x);
    }
    dfs(1, 0);
    while(M--) {
        int x = read(), y = read();
        printf("%d\n", Modify(x, y));
    }
    return 0;
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-02-24 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
洛谷P1501 [国家集训队]Tree II(LCT)
题目描述 一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一: + u v c:将u到v的路径上的点的权值都加上自然数c; - u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树; \* u v c:将u到v的路径上的点的权值都乘上自然数c; / u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。 输入输出格式 输入格式: 第一行两个整数n,q 接下来n-1行每行两个
attack
2018/05/30
4370
洛谷P3224 [HNOI2012]永无乡
题目描述 永无乡包含 n 座岛,编号从 1 到 n,每座岛都有自己的独一无二的重要度,按照重要度可 以将这 n 座岛排名,名次用 1 到 n 来表示。某些岛之间由巨大的桥连接,通过桥可以从一个岛 到达另一个岛。如果从岛 a 出发经过若干座(含 0 座)桥可以到达岛 b,则称岛 a 和岛 b 是连 通的。 现在有两种操作: B x y 表示在岛 x 与岛 y 之间修建一座新桥。 Q x k 表示询问当前与岛 x连通的所有岛中第 k 重要的是哪座岛,即所有与岛 x 连通的岛中重要度排名第 k 小的岛是哪 座,请
attack
2018/04/11
5550
BZOJ1969: [Ahoi2005]LANE 航线规划(LCT)
Time Limit: 10 Sec  Memory Limit: 64 MB Submit: 587  Solved: 259 [Submit][Status][Discuss] Description 对Samuel星球的探险已经取得了非常巨大的成就,于是科学家们将目光投向了Samuel星球所在的星系——一个巨大的由千百万星球构成的Samuel星系。 星际空间站的Samuel II巨型计算机经过长期探测,已经锁定了Samuel星系中许多星球的空间坐标,并对这些星球从1开始编号1、2、3……。 一些先遣飞
attack
2018/05/30
6340
BZOJ3669: [Noi2014]魔法森林(瓶颈生成树 LCT)
为了得到书法大家的真传,小E同学下定决心去拜访住在魔法森林中的隐士。魔法森林可以被看成一个包含个N节点M条边的无向图,节点标号为1..N,边标号为1..M。初始时小E同学在号节点1,隐士则住在号节点N。小E需要通过这一片魔法森林,才能够拜访到隐士。
attack
2018/07/27
2670
洛谷P3380 【模板】二逼平衡树(树套树)
您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:
attack
2018/07/27
9650
洛谷P3165 [CQOI2014]排序机械臂
题目描述 为了把工厂中高低不等的物品按从低到高排好序,工程师发明了一种排序机械臂。它遵循一个简单的排序规则,第一次操作找到摄低的物品的位置P1,并把左起第一个至P1间的物品反序;第二次找到第二低的物品的位置P2,并把左起第二个至P2间的物品反序...最终所有的物品都会被排好序。 上图给出_个示例,第_次操作前,菝低的物品在位置4,于是把第1至4的物品反序;第二次操作前,第二低的物品在位罝6,于是把第2至6的物品反序... 你的任务便是编写一个程序,确定一个操作序列,即每次操作前第i低的物品所在位置Pi,以便
attack
2018/04/11
6530
BZOJ2002: [Hnoi2010]Bounce 弹飞绵羊(LCT)
Time Limit: 10 Sec  Memory Limit: 259 MB Submit: 13753  Solved: 6983 [Submit][Status][Discuss] Description 某天,Lostmonkey发明了一种超级弹力装置,为了在他的绵羊朋友面前显摆,他邀请小绵羊一起玩个游戏。游戏一开始,Lostmonkey在地上沿着一条直线摆上n个装置,每个装置设定初始弹力系数ki,当绵羊达到第i个装置时,它会往后弹ki步,达到第i+ki个装置,若不存在第i+ki个装置,则绵羊被弹
attack
2018/05/30
4090
Link-Cut-Tree(LCT)详解
LCT是一种解决动态树问题的方法,由tarjan(为什么又是他)在1982年提出,最原始的论文在这里,在论文中,tarjan除了介绍了均摊复杂度为$O(log^2n)$的LCT之外,还介绍了一种严格$O(log^2n)$的算法,不过本人太弱了,看不懂tarjan讲了些啥,也没找到其他的学习资料,因此这种算法我们不做讨论
attack
2018/05/01
2.4K5
Link-Cut-Tree(LCT)详解
洛谷P3391 【模板】文艺平衡树(Splay)
题目背景 这是一道经典的Splay模板题——文艺平衡树。 题目描述 您需要写一种数据结构(可参考题目标题),来维护一个有序数列,其中需要提供以下操作:翻转一个区间,例如原有序序列是5 4 3 2 1,翻转区间是[2,4]的话,结果是5 2 3 4 1 输入输出格式 输入格式: 第一行为n,m n表示初始序列有n个数,这个序列依次是(1,2, \cdots n-1,n)(1,2,⋯n−1,n) m表示翻转操作次数 接下来m行每行两个数 [l,r][l,r] 数据保证 1 \leq l \leq r \leq
attack
2018/04/11
8920
洛谷P3871 [TJOI2010]中位数(splay)
题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从小到大排序后处在中间位置的数。(若序列长度为偶数,则指处在中间位置的两个数中较小的那个) 例1:1 2 13 14 15 16 中位数为13 例2:1 3 5 7 10 11 17 中位数为7 例3:1 1 1 2 3 中位数为1 输入输出格式 输入格式: 第一行为初始序列长度N。第二行为N个整数,表示整数序列
attack
2018/07/05
4630
BZOJ1014: [JSOI2008]火星人prefix(splay 二分 hash)
题意 题目链接 Sol 一眼splay + 二分hash,不过区间splay怎么写来着呀 试着写了两个小时发现死活不对 看了一下yyb的代码发现自己根本就不会splay。。。。 // luogu-judger-enable-o2 #include<bits/stdc++.h> #define ull unsigned long long using namespace std; const int MAXN = 1e6 + 10; const ull base = 27; inline int read(
attack
2018/12/19
5760
各种平衡树
记一下自己写的平衡树 方便以后复制粘贴 题目链接 Vector 最快:284ms 1 #include<cstdio> 2 #include<vector> 3 #include<algorithm> 4 using namespace std; 5 const int MAXN=100005; 6 vector<int>v; 7 int n,opt,x; 8 inline char nc() 9 { 10 static char buf[MAXN],*p1=buf,*p2=buf
attack
2018/04/11
8670
洛谷P2147 [SDOI2008]Cave 洞穴勘测
题目描述 辉辉热衷于洞穴勘测。 某天,他按照地图来到了一片被标记为JSZX的洞穴群地区。经过初步勘测,辉辉发现这片区域由n个洞穴(分别编号为1到n)以及若干通道组成,并且每条通道连接了恰好两个洞穴。假如两个洞穴可以通过一条或者多条通道按一定顺序连接起来,那么这两个洞穴就是连通的,按顺序连接在一起的这些通道则被称之为这两个洞穴之间的一条路径。 洞穴都十分坚固无法破坏,然而通道不太稳定,时常因为外界影响而发生改变,比如,根据有关仪器的监测结果,123号洞穴和127号洞穴之间有时会出现一条通道,有时这条通道又会因
attack
2018/04/11
6880
模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板模板
图论 最短路 SPFA 1 #include<cstdio> 2 #include<queue> 3 #include<cstring> 4 using namespace std; 5 c
attack
2018/04/12
33.7K0
Splay详解(二)
前言 在上一节中,我们讲述了Splay的核心操作rotate与splay 本节我会教大家如何用这两个函数实现各种强大的功能 为了方便讲解,我们拿这道题做例题来慢慢分析 利用splay实现各种功能 首先,我们需要定义一些东西 各种指针 struct node { int v;//权值 int fa;//父亲节点 int ch[2];//0代表左儿子,1代表右儿子 int rec;//这个权值的节点出现的次数 i
attack
2018/04/11
1.1K0
洛谷P2234 [HNOI2002]营业额统计
题目描述 Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。 Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况: 当最小波动值越大时,就说明营业情况越不稳定。 而分析整个公司的从成立到现
attack
2018/04/11
7500
洛谷P2234 [HNOI2002]营业额统计
P3369 【模板】普通平衡树(Treap/SBT)
题目描述 您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作: 插入x数 删除x数(若有多个相同的数,因只删除一个) 查询x数的排名(若有多个相同的数,因输出最小的排名) 查询排名为x的数 求x的前驱(前驱定义为小于x,且最大的数) 求x的后继(后继定义为大于x,且最小的数) 输入输出格式 输入格式: 第一行为n,表示操作的个数,下面n行每行有两个数opt和x,opt表示操作的序号(1<=opt<=6) 输出格式: 对于操作3,4,5,6每行输出一个数,
attack
2018/04/12
5790
洛谷P2286 [HNOI2004]宠物收养场
题目描述 凡凡开了一间宠物收养场。收养场提供两种服务:收养被主人遗弃的宠物和让新的主人领养这些宠物。 每个领养者都希望领养到自己满意的宠物,凡凡根据领养者的要求通过他自己发明的一个特殊的公式,得出该领养者希望领养的宠物的特点值a(a是一个正整数,a<2^31),而他也给每个处在收养场的宠物一个特点值。这样他就能够很方便的处理整个领养宠物的过程了,宠物收养场总是会有两种情况发生:被遗弃的宠物过多或者是想要收养宠物的人太多,而宠物太少。 被遗弃的宠物过多时,假若到来一个领养者,这个领养者希望领养的宠物的特点值为
attack
2018/04/11
6820
洛谷P3313 [SDOI2014]旅行(树链剖分 动态开节点线段树)
题意 题目链接 Sol 树链剖分板子 + 动态开节点线段树板子 #include<bits/stdc++.h> #define Pair pair<int, int> #define MP(x, y) make_pair(x, y) #define fi first #define se second //#define int long long #define LL long long #define Fin(x) {freopen(#x".in","r",stdin);} #define Fou
attack
2019/03/01
5450
震惊!Vector两行代码求逆序对,六行代码过普通平衡树
Vector两行代码求逆序对 背景:济南集训Day7上午T2,出了一道逆序对的裸题,SB的我没看出是逆序对来,于是现场推了一个很刁钻的求逆序对的方法 首先我们想一下冒泡排序的过程,我们不难发现,对于每一个元素,我们实际上是让他不停的和前面的元素比较,交换。 也正是因为这个过程决定了在冒泡排序的过程中:一个位置的数的前面的数一定是递增的(从小到大排的话) 那么我们在交换的时候,直接二分找到一个合适的位置,插入即可 这个很显然可以用平衡树Vector实现 代码也非常短, 1 #include<cstdi
attack
2018/04/11
7930
相关推荐
洛谷P1501 [国家集训队]Tree II(LCT)
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验