[树链剖分][SDOI 2011]染色,Housewife Wind

文章目录

  • T1:Housewife Wind
    • 题目
    • 题解
    • code
  • T2:染色
    • 题目
    • 题解
    • code

今天选择写这篇博客主要是为了告诉大家一个道理,数组比vectorvectorvector快太多了,我这两道题第一次都因为vectorvectorvectorTTT到飞起
在这里插入图片描述

T1:Housewife Wind

题目

After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beautiful huts. There are some pairs of huts connected by bidirectional roads. We say that huts in the same pair directly connected. XX Village is so special that we can reach any other huts starting from an arbitrary hut. If each road cannot be walked along twice, then the route between every pair is unique.

Since Jiajia earned enough money, Wind became a housewife. Their children loved to go to other kids, then make a simple call to Wind: ‘Mummy, take me home!’

At different times, the time needed to walk along a road may be different. For example, Wind takes 5 minutes on a road normally, but may take 10 minutes if there is a lovely little dog to play with, or take 3 minutes if there is some unknown strange smell surrounding the road.

Wind loves her children, so she would like to tell her children the exact time she will spend on the roads. Can you help her?
Input
The first line contains three integers n, q, s. There are n huts in XX Village, q messages to process, and Wind is currently in hut s. n < 100001 , q < 100001.

The following n-1 lines each contains three integers a, b and w. That means there is a road directly connecting hut a and b, time required is w. 1<=w<= 10000.

The following q lines each is one of the following two types:

Message A: 0 u
A kid in hut u calls Wind. She should go to hut u from her current position.
Message B: 1 i w
The time required for i-th road is changed to w. Note that the time change will not happen when Wind is on her way. The changed can only happen when Wind is staying somewhere, waiting to take the next kid.
Output
For each message A, print an integer X, the time required to take the next child.
Sample Input
3 3 1
1 2 1
2 3 2
0 2
1 2 3
0 3
Sample Output
1
3

题解

其实这道题就是一个边权模板题,这篇博客的重点是后面的染色
其次这道题我被卡了vectorvectorvector所以来记录一下数组版怎么写罢了vector版边权模板
我觉得没有什么讲的必要,直接上就行了,如果刚刚踏入门的话,→移步入门树链剖分
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 100005
struct noded {int u, v;int w;noded () {}noded ( int U, int V, int W ) {u = U;v = V;w = W;}
}tmp[maxn];
struct EDGE {int to, next;
}edge[maxn << 1];
int cnt = 1, n, q, s;
int f[maxn], son[maxn], dep[maxn], Size[maxn];
int id[maxn], Top[maxn];
int tree[maxn << 2];
int head[maxn];void update ( int t, int l, int r, int idx, int val ) {if ( l == r ) {tree[t] = val;return;}int mid = ( l + r ) >> 1;if ( idx <= mid )update ( t << 1, l, mid, idx, val );elseupdate ( t << 1 | 1, mid + 1, r, idx, val );tree[t] = tree[t << 1] + tree[t << 1 | 1];
}int query ( int t, int l, int r, int L, int R ) {if ( L <= l && r <= R )return tree[t];int mid = ( l + r ) >> 1;int ans = 0;if ( L <= mid )ans += query ( t << 1, l, mid, L, R );if ( mid < R )ans += query ( t << 1 | 1, mid + 1, r, L, R );return ans;
}void addedge ( int u, int v ) {edge[cnt].to = v;edge[cnt].next = head[u];head[u] = cnt ++;
}void dfs1 ( int u, int fa, int depth ) {f[u] = fa;dep[u] = depth;Size[u] = 1;for ( int i = head[u];i != -1;i = edge[i].next ) {int v = edge[i].to;if ( v == fa )continue;dfs1 ( v, u, depth + 1 );Size[u] += Size[v];if ( Size[v] > Size[son[u]] || ! son[u] )son[u] = v;}
}void dfs2 ( int u, int t ) {Top[u] = t;id[u] = ++ cnt;if ( ! son[u] )return;dfs2 ( son[u], t );for ( int i = head[u];i != -1;i = edge[i].next ) {int v = edge[i].to;if ( v != son[u] && v != f[u] )dfs2 ( v, v );}
}int solve ( int x, int y ) {int ans = 0;int fx = Top[x], fy = Top[y];while ( fx != fy ) {if ( dep[fx] > dep[fy] ) {ans += query ( 1, 1, n, id[fx], id[x] );x = f[fx];fx = Top[x];}else {ans += query ( 1, 1, n, id[fy], id[y] );y = f[fy];fy = Top[y];}}if ( id[x] < id[y] )ans += query ( 1, 1, n, id[x] + 1, id[y] );elseans += query ( 1, 1, n, id[y] + 1, id[x] );return ans;
}int main() {scanf ( "%d %d %d", &n, &q, &s );memset ( head, -1, sizeof ( head ) );for ( int i = 1;i < n;i ++ ) {scanf ( "%d %d %d", &tmp[i].u, &tmp[i].v, &tmp[i].w );addedge ( tmp[i].u, tmp[i].v );addedge ( tmp[i].v, tmp[i].u );}cnt = 0;//建边的时候不小心用到了,一定要清零 dfs1 ( 1, 0, 1 );dfs2 ( 1, 0 );for ( int i = 1;i < n;i ++ ) {if ( dep[tmp[i].u] > dep[tmp[i].v] )swap ( tmp[i].u, tmp[i].v );update ( 1, 1, cnt, id[tmp[i].v], tmp[i].w );}int opt, x, w;for ( int i = 1;i <= q;i ++ ) {scanf ( "%d %d", &opt, &x );if ( opt ) {scanf ( "%d", &w );update ( 1, 1, n, id[tmp[x].v], w );}else {printf ( "%d\n", solve ( s, x ) );s = x;//注意接完孩子后,mom就待在了那里}}return 0;
}

T2:染色

题目

给定一棵有n个节点的无根树和m个操作,操作有2类:
1、将节点a到节点b路径上所有点都染成颜色c;
2、询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),
如“112221”由3段组成:“11”、“222”和“1”。
请你写一个程序依次完成这m个操作。
Input
第一行包含2个整数n和m,分别表示节点数和操作数;
第二行包含n个正整数表示n个节点的初始颜色
下面 行每行包含两个整数x和y,表示x和y之间有一条无向边。
下面 行每行描述一个操作:
“C a b c”表示这是一个染色操作,把节点a到节点b路径上所有点(包括a和b)都染成颜色c;
“Q a b”表示这是一个询问操作,询问节点a到节点b(包括a和b)路径上的颜色段数量。
Output
对于每个询问操作,输出一行答案。

Sample Input
6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5
Sample Output
3
1
2
Hint
N<=105N<=10^5N<=105,操作数M<=105M<=10^5M<=105,所有的颜色C为整数且在[0, 10^9]之间。

题解

其实这道题说难也不难,简单也不简单
在这里插入图片描述


首先这个是点权题,降低了一定难度,其次改颜色的操作也是模板,我们直接进入如何统计颜色段数
在这里插入图片描述
可以知道当两个区间进行合并的时候,交接处如果颜色相同的话,就并成了一段颜色,所以我们就要在线段树时判断,可以返回一个结构体带三个参数最左边的颜色最右边的颜色和颜色的段数

然后就是树链剖分的时候我们要记录上一次的左右颜色,分别于两个点的左右进行合并判断,这里主要是考察码力,可以直接看solvesolvesolve函数,我稍微改变了一下写法
在这里插入图片描述

code

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
#define maxn 100005
#define INF 0x7f7f7f7f
struct node {//用vector太慢了 int next, v;
}edge[maxn << 1];
struct noded {int lcolor, rcolor, sum;
}tree[maxn << 2];
int head[maxn], tag[maxn << 2];
int cnt;
int f[maxn], son[maxn], dep[maxn], Size[maxn];
int id[maxn], top[maxn];
int color[maxn];void addedge ( int x, int y ) {cnt ++;edge[cnt].next = head[x];edge[cnt].v = y;head[x] = cnt;
}void pushdown ( int t ) {//不用lazy标记要超时 if ( ! tag[t] )return;tree[t << 1].lcolor = tree[t << 1].rcolor = tree[t << 1 | 1].lcolor = tree[t << 1 | 1].rcolor = tag[t];tag[t << 1] = tag[t << 1 | 1] = tag[t];tag[t] = 0;tree[t].sum = tree[t << 1].sum = tree[t << 1 | 1].sum = 1;
}void update ( int t, int l, int r, int L, int R, int v ) {if ( L <= l && r <= R ) {tree[t].lcolor = tree[t].rcolor = tag[t] = v;tree[t].sum = 1;return;}pushdown ( t );int mid = ( l + r ) >> 1;if ( L <= mid )update ( t << 1, l, mid, L, R, v );if ( mid < R )update ( t << 1 | 1, mid + 1, r, L, R, v );tree[t].sum = tree[t << 1].sum + tree[t << 1 | 1].sum;if ( tree[t << 1].rcolor == tree[t << 1 | 1].lcolor )//判断左右儿子的相接处是否颜色一样 tree[t].sum --;tree[t].lcolor = tree[t << 1].lcolor;tree[t].rcolor = tree[t << 1 | 1].rcolor;
}noded query ( int t, int l, int r, int L, int R ) {if ( L <= l && r <= R )return tree[t];int mid = ( l + r ) >> 1;pushdown ( t );if ( R <= mid )return query ( t << 1, l, mid, L, R );else if ( mid < L )return query ( t << 1 | 1, mid + 1, r, L, R );else {noded ans, ans1 = query ( t << 1, l, mid, L, R ), ans2 = query ( t << 1 | 1, mid + 1, r, L, R );ans.lcolor = ans1.lcolor;ans.rcolor = ans2.rcolor;ans.sum = ans1.sum + ans2.sum;if ( ans1.rcolor == ans2.lcolor )ans.sum --;return ans;}
}void dfs1 ( int u, int fa, int depth ) {f[u] = fa;dep[u] = depth;Size[u] = 1;for ( int i = head[u];i != -1;i = edge[i].next ) {int v = edge[i].v;if ( v == fa )continue;dfs1 ( v, u, depth + 1 );Size[u] += Size[v];if ( Size[v] > Size[son[u]] || ! son[u] )son[u] = v;}
}void dfs2 ( int u, int t ) {top[u] = t;id[u] = ++ cnt;if ( ! son[u] )return;dfs2 ( son[u], t );for ( int i = head[u];i != -1;i = edge[i].next ) {int v = edge[i].v;if ( v != son[u] && v != f[u] )dfs2 ( v, v );}
}void solve ( int x, int y ) {int ans = 0, fx = top[x], fy = top[y];int xcolor = -1, ycolor = -1;noded ret;while ( fx != fy ) {if ( id[fx] < id[fy] ) {swap ( x, y );swap ( fx, fy );swap ( xcolor, ycolor );}ret = query ( 1, 1, cnt, id[fx], id[x] );ans += ret.sum;if ( ret.rcolor == xcolor )ans --;xcolor = ret.lcolor;x = f[fx];fx = top[x];}if ( id[x] > id[y] ) {swap ( x, y );swap ( xcolor, ycolor );}ret = query ( 1, 1, cnt, id[x], id[y] );ans += ret.sum;if ( xcolor == ret.lcolor )ans --;if ( ycolor == ret.rcolor )ans --;printf ( "%d\n", ans );
}void solve_update ( int x, int y, int c ) {int fx = top[x], fy = top[y];while ( fx != fy ) {if ( dep[fx] >= dep[fy] ) {update ( 1, 1, cnt, id[fx], id[x], c );x = f[fx];fx = top[x];}else {update ( 1, 1, cnt, id[fy], id[y], c );y = f[fy];fy = top[y];}}if ( id[x] <= id[y] )update ( 1, 1, cnt, id[x], id[y], c );elseupdate ( 1, 1, cnt, id[y], id[x], c );
}int main() {int n, m;memset ( head, -1, sizeof ( head ) );scanf ( "%d %d", &n, &m );for ( int i = 1;i <= n;i ++ )scanf ( "%d", &color[i] );for ( int i = 1;i < n;i ++ ) {int a, b;scanf ( "%d %d", &a, &b );addedge ( a, b );addedge ( b, a );}cnt = 0;dfs1 ( 1, 0, 1 );dfs2 ( 1, 0 );for ( int i = 1;i <= n;i ++ )update ( 1, 1, cnt, id[i], id[i], color[i] );char opt[2];int a, b, c;for ( int i = 1;i <= m;i ++ ) {scanf ( "%s %d %d", opt, &a, &b );if ( opt[0] == 'C' ) {scanf ( "%d", &c );solve_update ( a, b, c );}else solve ( a, b );}return 0;
}

看不懂的欢迎评论
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/318006.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

最长上升子序列模型

有两个模板&#xff1a; 最长上升子序列这类题目都是这俩变形而来 最长上升子序列模型 AcWing 1017. 怪盗基德的滑翔翼1120人打卡 AcWing 1014. 登山1094人打卡 AcWing 482. 合唱队形1069人打卡 AcWing 1012. 友好城市1040人打卡 AcWing 1016. 最大上升子序列和1048人打卡 AcWi…

YBTOJ:向量问题(线段树分治、凸包)

文章目录题目描述数据范围解析代码题目描述 你要维护一个向量集合&#xff0c;支持以下操作&#xff1a; 插入一个向量 。 删除插入的第 x 个向量。 查询当前集合与(x,y)(x,y)(x,y) 点积的最大值是多少。如果当前是空集输出0。 数据范围 n<2e5,x、y∈[1,2e6]n<2e5,x、y∈…

ASP.NET Core 网站运行时修改设置如何自动生效

点击蓝字关注我在ASP.NET Core中&#xff0c;如果修改了appsettings.json中的设置&#xff0c;那么默认情况下就得重启网站才能生效。有没有办法在修改设置后自动刷新并应用呢&#xff1f;背景首先&#xff0c;我们看看默认模板建出来的 ASP.NET Core 网站&#xff0c;配置文件…

AGC004(A~E)

前言 FFF不会做&#xff0c;正解好神仙&#xff0c;爬了 正题 AT2041 [AGC004A] Divide a Cuboid https://www.luogu.com.cn/problem/AT2041 题目大意 一个A∗B∗CA*B*CA∗B∗C的立方体&#xff0c;分成两个长方体使得边长都是整数而且体积差最小。 1≤A,B,C≤1091\leq A,B…

1022. 宠物小精灵之收服

1022. 宠物小精灵之收服 题意&#xff1a; 现在有n个胶囊&#xff0c;m个生命值&#xff0c;k个怪物&#xff0c;每个怪物需要a[i]个胶囊&#xff0c;且会造成b[i]个伤害后才能捕获&#xff0c;问在活着的前提下&#xff0c;最多捕获多少怪物&#xff0c;在怪物最多的情况下剩…

平衡树 - FHQ 学习笔记

平衡树 - FHQ 学习笔记 主要参考万万没想到 的 FHQ-Treap学习笔记。 本片文章的姊妹篇&#xff1a;平衡树 - Splay 学习笔记。 感觉完全不会平衡树&#xff0c;又重新学习了一遍 FHQ&#xff0c;一口气把常见套路都学完了。 一、大致内容及分类 FHQ(???)&#xff0c;全称非旋…

【周末狂欢赛6】[AT1219]历史研究(回滚莫队),大魔法师(矩阵+线段树),单峰排列

文章目录T1&#xff1a;单峰排列题目题解codeT2&#xff1a;历史研究题目题解codeT3&#xff1a;大魔法师题目题解code我可能这辈子都更不出来狂欢赛5了&#xff0c;先咕咕 T1&#xff1a;单峰排列 题目 一个n的全排列A[i]是单峰的&#xff0c;当且仅当存在某个x使得A[1]<…

YBTOJ:圈套问题(分治法、鸽笼原理)

文章目录题目描述数据范围解析代码图片转载自&#xff1a; https://blog.csdn.net/weixin_43346722/article/details/118435430题目描述 平面上有 n个点&#xff0c;用n个大小相同的圆分别将一个点作为圆心&#xff0c;同时满足圆圈不相交&#xff0c;求圆的最大半径。 数据范…

CF1598E-Staircases【计数】

正题 题目链接:https://www.luogu.com.cn/problem/CF1598E 题目大意 给出一个nmn\times mnm的网格图&#xff0c;开始所有都是黑色的&#xff0c;qqq次取反一个格子的颜色&#xff0c;然后求楼梯的数量。 楼梯定义为全黑色的下/右交替的格子集。 1≤n,m≤1000,1≤q≤1041\le…

ASP.NET Core 实战:使用 NLog 将日志信息记录到 MongoDB

一、前言在项目开发中&#xff0c;日志系统是系统的一个重要组成模块&#xff0c;通过在程序中记录运行日志、错误日志&#xff0c;可以让我们对于系统的运行情况做到很好的掌控。同时&#xff0c;收集日志不仅仅可以用于诊断排查错误&#xff0c;由于日志同样也是大量的数据&a…

532. 货币系统

532. 货币系统 题意&#xff1a; 有 n 种不同面额的货币&#xff0c;第 i 种货币的面额为 a[i]&#xff0c;每一种货币都有无穷多张&#xff0c;货币之间可以彼此代替&#xff0c;比如6等于两张3&#xff0c;问有多少种货币是不可替代的 题解&#xff1a; 我们换一个问…

概率期望题(期望 DP)做题记录

概率期望题(期望 DP)做题记录 P3830 [SHOI2012]随机树 难点在于第二问&#xff1a;生成树的期望深度。 不 wei zhuo 捏&#xff0c;设 \(dp_{i,j}\) 表示已经有了 \(i\) 个叶子结点&#xff0c;深度大于 \(j\) 的概率。 考虑枚举一棵子树的大小&#xff0c;转移方程如下&#x…

[学习笔记] 伸展树splay详解+全套模板+例题[Luogu P3369 【模板】普通平衡树]

文章目录引入概念全套模板变量声明updaterotate旋转splay操作insert插入delete删除查找x的位置查找第k大前驱/后继极小值-inf和极大值inf的作用例题&#xff1a;P3369 【模板】普通平衡树题目code声明一下&#xff0c;许多代码的注解都在模板代码里面写了的&#xff0c;所以正文…

2021.9.23模拟

前言 174pts 40502460 四个暴力分 qwq T1想切结果矩乘T飞了。。。 不要迷信矩乘&#xff0c;这玩意也是会T的… 考场 先看题 感觉T1和T最可做 T3期望想到zld的全排列大法了&#xff0c;但是似乎只能线性… T4是初始化加强版&#xff0c;思路倒是有&#xff0c;但是不想写&am…

AT1981-[AGC001C]Shorten Diameter

正题 题目链接:https://www.luogu.com.cn/problem/AT1981 题目大意 给出nnn个点的一棵树&#xff0c;每次你可以删除一个叶子&#xff0c;求最少的操作数使得树的直径长度不超过kkk。 1≤n,k≤20001\leq n,k\leq 20001≤n,k≤2000 解题思路 开始以为是dpdpdp啥的&#xff0c…

手写AspNetCore 认证授权代码

在普通的MVC项目中 我们普遍的使用Cookie来作为认证授权方式&#xff0c;使用简单。登录成功后将用户信息写入Cookie&#xff1b;但当我们做WebApi的时候显然Cookie这种方式就有点不适用了。在dotnet core 中 WebApi中目前比较流行的认证授权方式是Jwt (Json Web Token) 技术。…

FWT 学习笔记

FWT 学习笔记 学的时候比较匆忙&#xff0c;于是就学一个 \(\texttt{or,and,xor}\) 卷积跑路。 P4717 【模板】快速莫比乌斯/沃尔什变换 (FMT/FWT) 前置知识&#xff1a;高维前缀和&#xff0c;下面前缀和的操作大多都是用高维前缀和来实现的。 设有两个长度为 \(2^n\) 的序列 …

大盗阿福

大盗阿福 题意&#xff1a; 长度为n的数组a&#xff0c;不能取连续的数&#xff0c;问所能取的最大值是多少 题解&#xff1a; 设dp[i][0]表示第i个数不选&#xff0c;dp[i][1]表示第i个数选 如果第i个数不选&#xff0c;那么第i-1个数可以选也可以不选&#xff0c;我们取最…

YBTOJ:采矿战略(线段树维护dp、树链剖分)

文章目录题目描述解析代码题目描述 所谓线段树维护dp&#xff0c;就是在线段树上维护dp &#xff08;逃&#xff09; 解析 把树剖一下后就变成了区间问题 考虑建一棵线段树&#xff0c;每一个结点都是一个背包 这样就能区间查询&#xff0c;也能带修了 这种做法复杂度其实并不…

【用皇宫三十六计生存法则带你走进LCT(动态树)】LCT概念+模板+例题【洛谷P3690 Link Cut Tree(动态树)】

文章目录LCT概念模板rotatoisrootsplayaccessmakerootsplitfindrootlinkcut封装版例题题目code普通版code封装版这篇博客主要是帮助大家理解各个模板及LCTLCTLCT的意思&#xff0c;方便理解&#xff0c;模板写法的理解在代码里有注释详解&#xff0c;如果要看原理的话&#xff…