BZOJ3531 树剖 + 动态开点线段树

时间:2023-01-22 19:25:12

https://www.lydsy.com/JudgeOnline/problem.php?id=3531

首先这题意要求树链上的最大值以及求和,其树链剖分的做法已经昭然若揭

问题在于这次的信息有宗教条件下的限制,导致不那么容易维护。

第一个想法自然是对于每一个宗教都建一颗线段树,看一下数据范围,宗教的范围是1e5,N的范围也是1e5,又好像空间不那么允许。

事实上可以采用动态线段树的方法节省一波空间,整个做法就变得科学了起来。

如果不是因为我的愚蠢在树剖的重链部分写挂了导致T了很久,这题还是很温暖的

#include <map>
#include <set>
#include <ctime>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <string>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <sstream>
#include <iostream>
#include <algorithm>
#include <functional>
using namespace std;
#define For(i, x, y) for(int i=x;i<=y;i++)
#define _For(i, x, y) for(int i=x;i>=y;i--)
#define Mem(f, x) memset(f,x,sizeof(f))
#define Sca(x) scanf("%d", &x)
#define Sca2(x,y) scanf("%d%d",&x,&y)
#define Sca3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define Scl(x) scanf("%lld",&x);
#define Pri(x) printf("%d\n", x)
#define Prl(x) printf("%lld\n",x);
#define CLR(u) for(int i=0;i<=N;i++)u[i].clear();
#define LL long long
#define ULL unsigned long long
#define mp make_pair
#define PII pair<int,int>
#define PIL pair<int,long long>
#define PLL pair<long long,long long>
#define pb push_back
#define fi first
#define se second
typedef vector<int> VI;
int read(){int x = ,f = ;char c = getchar();while (c<'' || c>''){if (c == '-') f = -;c = getchar();}
while (c >= ''&&c <= ''){x = x * + c - '';c = getchar();}return x*f;}
const double eps = 1e-;
const int maxn = 1e5 + ;
const int INF = 0x3f3f3f3f;
const int mod = 1e9 + ;
int N,M,K;
inline int max(int a,int b){
return a>b?a:b;
}
PII node[maxn];
struct Edge{
int to,next;
}edge[maxn * ];
int head[maxn],Tot;
void init(){
for(int i = ; i <= N ; i ++) head[i] = -;
Tot = ;
}
void add(int u,int v){
edge[Tot].to = v;
edge[Tot].next = head[u];
head[u] = Tot++;
}
int size[maxn],top[maxn],fa[maxn],son[maxn];
int dep[maxn],pos[maxn];
void dfs(int t,int la){
size[t] = ; son[t] = ;
int heavy = ;
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(v == la) continue;
fa[v] = t;
dep[v] = dep[t] + ;
dfs(v,t);
if(heavy < size[v]){
heavy = size[v];
son[t] = v;
}
size[t] += size[v];
}
}
int cnt;
void dfs2(int t,int la){
top[t] = la;
pos[t] = ++cnt;
if(!son[t]) return;
dfs2(son[t],la);
for(int i = head[t]; ~i ; i = edge[i].next){
int v = edge[i].to;
if(fa[t] == v || son[t] == v) continue;
dfs2(v,v);
}
}
struct Tree{
int Max,sum;
int lt,rt;
void init(){
Max = sum = lt = rt = ;
}
}tree[maxn * ];
int tot;
int thead[maxn];
void check(int &t){
if(t) return;
t = ++tot;
tree[t].init();
}
void Pushup(int t){
int ls = tree[t].lt,rs = tree[t].rt;
check(ls);check(rs);
tree[t].sum = tree[ls].sum + tree[rs].sum;
tree[t].Max = max(tree[ls].Max,tree[rs].Max);
}
void update(int &t,int l,int r,int p,int w){
check(t);
if(l == r){
tree[t].Max = tree[t].sum = w;
return;
}
int m = (l + r) >> ;
if(p <= m) update(tree[t].lt,l,m,p,w);
else update(tree[t].rt,m + ,r,p,w);
Pushup(t);
}
void update(int i,int w){
update(thead[node[i].se],,N,pos[i],w);
}
int query(int &t,int l,int r,int L,int R,int p){
check(t);
if(L <= l && r <= R){
if(p) return tree[t].sum;
else return tree[t].Max;
}
int m = (l + r) >> ;
if(R <= m) return query(tree[t].lt,l,m,L,R,p);
else if(L > m) return query(tree[t].rt,m + ,r,L,R,p);
else{
if(p) return query(tree[t].lt,l,m,L,m,p) + query(tree[t].rt,m + ,r,m + ,R,p);
else return max(query(tree[t].lt,l,m,L,m,p),query(tree[t].rt,m + ,r,m + ,R,p));
}
}
int query(int u,int v,int flag){
int ans = ;
int &c = thead[node[u].se];
while(top[u] != top[v]){
if(dep[top[u]] < dep[top[v]]) swap(u,v);
if(flag) ans += query(c,,N,pos[top[u]],pos[u],);
else ans = max(ans,query(c,,N,pos[top[u]],pos[u],));
u = fa[top[u]];
}
if(dep[u] > dep[v]) swap(u,v);
if(flag) ans += query(c,,N,pos[u],pos[v],);
else ans = max(ans,query(c,,N,pos[u],pos[v],));
return ans;
}
int main(){
Sca2(N,M); init();
for(int i = ; i <= N ; i ++) node[i].fi = read(),node[i].se = read();
for(int i = ; i <= N - ; i ++){
int u = read(),v = read();
add(u,v); add(v,u);
}
int root = ;
dfs(root,); dfs2(root,root);
for(int i = ; i <= N; i ++) update(i,node[i].fi);
for(int i = ; i <= M ; i ++){
char op[];
scanf("%s",op);
int x = read(),y = read();
if(op[] == 'C'){
if(op[] == 'C'){
update(x,);
node[x].se = y;
update(x,node[x].fi);
}else{
node[x].fi = y;
update(x,y);
}
}else{
if(op[] == 'S'){
Pri(query(x,y,)); //sum
}else{
Pri(query(x,y,)); //Max
}
}
}
return ;
}

BZOJ3531 树剖 + 动态开点线段树的更多相关文章

  1. BZOJ 3531&colon; &lbrack;Sdoi2014&rsqb;旅行 &lpar;树剖&plus;动态开点线段树&rpar;

    对于每种信仰维护一棵动态开点线段树就行了- #include <cstdio> #include <cctype> #include <cstring> #incl ...

  2. CF915E Physical Education Lessons 动态开点线段树

    题目链接 CF915E Physical Education Lessons 题解 动态开点线段树 代码 /* 动态开点线段树 */ #include<cstdio> #include&l ...

  3. bzoj3531&colon; &lbrack;Sdoi2014&rsqb;旅行 (树链剖分 &amp&semi;&amp&semi; 动态开点线段树)

    感觉动态开点线段树空间复杂度好优秀呀 树剖裸题 把每个宗教都开一颗线段树就可以了 但是我一直TLE 然后调了一个小时 为什么呢 因为我 #define max(x, y) (x > y ? x ...

  4. NFLSOJ &num;917 -「lych&lowbar;cys模拟题2018」橘子树(树剖&plus;ODT&plus;莫反统计贡献的思想&plus;动态开点线段树)

    题面传送门 sb 出题人不在题面里写 \(b_i=0\) 导致我挂成零蛋/fn/fn 首先考虑树链剖分将路径问题转化为序列上的问题,因此下文中简称"位置 \(i\)"表示 DFS ...

  5. &lbrack;ZJOI2019&rsqb;语言(树链剖分&plus;动态开点线段树&plus;启发式合并)

    首先,对于从每个点出发的路径,答案一定是过这个点的路径所覆盖的点数.然后可以做树上差分,对每个点记录路径产生总贡献,然后做一个树剖维护,对每个点维护一个动态开点线段树.最后再从根节点开始做一遍dfs, ...

  6. &lbrack;2016湖南长沙培训Day4&rsqb;&lbrack;前鬼后鬼的守护 chen&rsqb; &lpar;动态开点线段树&plus;中位数 or 动规 or 贪心&plus;堆优化&rpar;

    题目大意 给定一个长度为n的正整数序列,令修改一个数的代价为修改前后两个数的绝对值之差,求用最小代价将序列转换为不减序列. 其中,n满足小于500000,序列中的正整数小于10^9 题解(引自mzx神 ...

  7. &lbrack;bzoj 3531&rsqb;&lbrack;SDOI2014&rsqb;旅行(树链剖分&plus;动态开点线段树)

    题目:http://www.lydsy.com:808/JudgeOnline/problem.php?id=3531 分析: 对于每个颜色(颜色<=10^5)都建立一颗线段树 什么!那么不是M ...

  8. 【BZOJ-4636】蒟蒻的数列 动态开点线段树 &vert;&vert;(离散化) &plus; 标记永久化

    4636: 蒟蒻的数列 Time Limit: 30 Sec  Memory Limit: 256 MBSubmit: 247  Solved: 113[Submit][Status][Discuss ...

  9. codeforces 893F - Physical Education Lessons 动态开点线段树合并

    https://codeforces.com/contest/893/problem/F 题意: 给一个有根树, 多次查询,每次查询对于$x$i点的子树中,距离$x$小于等于$k$的所有点中权值最小的 ...

随机推荐

  1. hihocoder挑战赛26

    某蒟蒻成功的·写出了T1并rank16...小岛的题目真难... 传送门:http://hihocoder.com/contest/challenge26 T1 如果你想要暴力枚举的话显然是不行的 如 ...

  2. 第六百一十六天 how can I 坚持

    有时间还是多学点东西吧,webservice.. 晚上看了个电影<我们的十年>,乔任梁死了..买了个大柚子,上火好难受.有些困惑啊. 有没有梦想,只是不想让人来到这这个世界,什么都没留下就 ...

  3. 使用merge同时执行insert和update操作

    SQL点滴18—SqlServer中的merge操作,相当地风骚   今天在一个存储过程中看见了merge这个关键字,第一个想法是,这个是配置管理中的概念吗,把相邻两次的更改合并到一起.后来在tech ...

  4. Codeforces 552C Vanya and Scales(思路)

    题目大概说有101个质量w0.w1.w2.....w100的砝码,和一个质量m的物品,问能否在天平两边放物品和砝码使其平衡. 哎,怎么没想到..注意到w0.w1.w2.....w100—— 把m转化成 ...

  5. Oracle常用sql

    Oracle不像Sqlserver,并没有提供l默认约束,但提供了默认值,效果一样.--------------------------- 在建表时设置默认约束-------------------- ...

  6. get Status canceled 请求被取消

    1.chrome浏览器下状况: 2.环境: 一个页面A下 包含一个 iframe ,在子页面中用js点击A页面下的链接替换iframe内容脚本如下: window.parent.document.ge ...

  7. AJAX顺序输出

    转载:http://www.cnblogs.com/niunan/archive/2010/10/13/1849873.html AJAX顺序输出  在安装大多数CMS的时候都会在安装界面上看到这样的 ...

  8. Java爬虫(一)利用GET和POST发送请求,获取服务器返回信息

    本人所使用软件 eclipse fiddle UC浏览器 分析请求信息 以知乎(https://www.zhihu.com)为例,模拟登陆请求,获取登陆后首页,首先就是分析请求信息. 用UC浏览器F1 ...

  9. &lbrack;转载&rsqb;MySQL5&period;6 PERFORMANCE&lowbar;SCHEMA 说明

    背景: MySQL 5.5开始新增一个数据库:PERFORMANCE_SCHEMA,主要用于收集数据库服务器性能参数.并且库里表的存储引擎均为PERFORMANCE_SCHEMA,而用户是不能创建存储 ...

  10. 权限系统与RBAC模型概述&lbrack;绝对经典&rsqb;

    0. 前言 一年前,我负责的一个项目中需要权限管理.当时凭着自己的逻辑设计出了一套权限管理模型,基本原理与RBAC非常相似,只是过于简陋.当时google了一些权限管理的资料,从中了解到早就有了RBA ...