Solution -「洛谷 P4689」「YunoOI 2016」这是我自己的发明
Description
Link.
给一个树,\(n\) 个点,有点权,初始根是 1。
\(m\) 个操作,种类如下:
1 x 将树根换为 \(x\)。
2 x y 给出两个点 \(x,y\),从 \(x\) 的子树中选每一个点,\(y\) 的子树中选每一个点,求点权相等的情况数。
Solution
我首先认为这是 SNOI2017 一个简单的询问 搬到树上。
我们传统地把此题分为两个 \(\texttt{pass}\),一个询问,一个修改。
- \(\texttt{pass 1}\):询问
我直接按 一个简单的询问 的方法讲。其实是把以前的题解 copy 过来了。
由于是出现次数,满足区间加减性,所以我们可以这样表达 \(\mathrm{get}(l,r,x)\)(省略 \(x\)):
\]
那么我们代进原式,化一波式子(\(\mathrm{get}(p)=\mathrm{get}(1,p,x)\)):
\]
\]
\]
\]
则答案为:
\]
考虑怎么更新,比如从 \(l\) 更新到 \(l+1\),则:
\]
\]
\]
其中 \(\mathrm{cont}(a_{l})\) 表示 \(a_{l}\) 的出现次数。
则我们就知道怎么更新了,由于我们维护和的是前缀信息,所以姿势和普通莫队有点不一样。
维护两个数组 cntl[x] 和 cntr[y] 表示答案式子
\]
子树的话直接 DFS 序拍到序列上。
- \(\texttt{pass 2}\):修改
现在我们面临着查询操作我们是用莫队整的,但这个修改貌似不单纯。其实也是从树剖模板缝合过来的。
分类讨论,设我们当前要换的根为 \(rt\),现在来处理询问,设查询的节点为 \(u\),\(\text{LCA}(u,v)\) 为节点 \(u\) 和节点 \(v\) 的最近公共祖先。
- 如果 \(rt=u\),则我们直接对整棵树进行查询。
- 如果 \(\text{LCA}(u,rt)\neq u\),此时修改不影响查询。
- 如果 \(\text{LCA}(u,rt)=u\),此时 \(rt\) 在 \(u\) 的子树里,那么需要查询的地方就很明确了,后面的步骤显然。
于是我们不需要实际的去处理这个修改,然后就可以直接莫队了。
(整体感觉是个 原题+假上树+树剖模板 的缝合题)
/* Clearink */
#include <cstdio>
#include <algorithm>
using namespace std;
typedef long long LL;
const int MAXN = 5e5 + 5, MAXM = 1e6 + 5;
int rint () {
int x = 0, f = 1; char c = getchar ();
for ( ; c < '0' || c > '9'; c = getchar () ) f = c == '-' ? -1 : f;
for ( ; c >= '0' && c <= '9'; c = getchar () ) x = ( x << 3 ) + ( x << 1 ) + ( c & 15 );
return x * f;
}
template<class _T>
void wint ( _T x ) {
if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
if ( x > 9 ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
}
template<class _T> void swapp ( _T& x, _T& y ) { _T w = x; x = y; y = w; }
struct GraphSet {
int to, nx;
GraphSet () : to ( 0 ), nx ( 0 ) {}
GraphSet ( const int a, const int b ) : to ( a ), nx ( b ) {}
} asg[MAXN * 2];
struct Quest {
int l, r, ID, x;
Quest () : l ( 0 ), r ( 0 ), ID ( 0 ), x ( 0 ) {}
Quest ( const int a, const int b, const int c, const int d ) : l ( a ), r ( b ), ID ( c ), x ( d ) {}
} asq[MAXM * 8], itls[MAXN];
LL cur = 0, ans[MAXM], buc1[MAXN], buc2[MAXN];
int rt, pos[MAXN], blo = 320, col[MAXN], freq;
int n, m, bgn[MAXN], cnt, sjc, segl[MAXN], segr[MAXN], kfa[MAXN][21], a[MAXN], dept[MAXN], pri[MAXN], len;
void addE ( const int u, const int v ) { asg[++ cnt] = GraphSet ( v, bgn[u] ), bgn[u] = cnt; }
bool existcmp ( const Quest& one, const Quest& ano ) { return pos[one.l] == pos[ano.l] ? one.r < ano.r : one.l < ano.l; }
void dfs ( const int u, const int lst ) {
kfa[u][0] = lst, dept[u] = dept[lst] + 1;
segl[u] = ++ sjc, col[sjc] = a[u];
for ( int i = 1; i <= 20; ++ i ) kfa[u][i] = kfa[kfa[u][i - 1]][i - 1];
for ( int i = bgn[u]; i; i = asg[i].nx ) {
int v = asg[i].to;
if ( v == lst ) continue;
dfs ( v, u );
}
segr[u] = sjc;
}
int calcKAC ( int u, int k ) {
for ( int i = 20; ~ i; -- i ) {
if ( k >= ( 1 << i ) ) k -= ( 1 << i ), u = kfa[u][i];
}
return u;
}
int calcLCA ( int u, int v ) {
if ( dept[u] < dept[v] ) swapp ( u, v );
for ( int i = 20; ~ i; -- i ) {
if ( dept[kfa[u][i]] >= dept[v] ) u = kfa[u][i];
}
if ( u == v ) return u;
for ( int i = 20; ~ i; -- i ) {
if ( kfa[u][i] != kfa[v][i] ) u = kfa[u][i], v = kfa[v][i];
}
return kfa[u][0];
}
void initial () {
for ( int i = 1; i <= n; ++ i ) pos[i] = ( i - 1 ) / blo + 1;
sort ( pri + 1, pri + 1 + n );
len = unique ( pri + 1, pri + 1 + n ) - pri - 1;
for ( int i = 1; i <= n; ++ i ) a[i] = lower_bound ( pri + 1, pri + 1 + len, a[i] ) - pri;
dfs ( 1, 0 );
}
void splitASdrug ( const int u, int& ils ) {
if ( u == rt ) itls[++ ils] = Quest ( 1, n, 0, 0 );
else {
int lca = calcLCA ( u, rt );
if ( lca != u ) itls[++ ils] = Quest ( segl[u], segr[u], 0, 0 );
else {
int ar = calcKAC ( rt, dept[rt] - dept[u] - 1 );
if ( 1 <= segl[ar] - 1 ) itls[++ ils] = Quest ( 1, segl[ar] - 1, 0, 0 );
if ( segr[ar] + 1 <= n ) itls[++ ils] = Quest ( segr[ar] + 1, n, 0, 0 );
}
}
}
void transASsub ( const int l1, const int r1, const int l2, const int r2, const int ID ) {
asq[++ m] = Quest ( r1, r2, ID, 1 ), asq[++ m] = Quest ( r1, l2 - 1, ID, -1 );
asq[++ m] = Quest ( l1 - 1, r2, ID, -1 ), asq[++ m] = Quest ( l1 - 1, l2 - 1, ID, 1 );
}
void transASmany ( const int l, const int r ) {
++ freq;
int ils = 0; splitASdrug ( l, ils );
int aim = ils; splitASdrug ( r, ils );
for ( int i = 1; i <= aim; ++ i ) {
for ( int j = aim + 1; j <= ils; ++ j ) transASsub ( itls[i].l, itls[i].r, itls[j].l, itls[j].r, freq );
}
}
void add1 ( const int x ) { cur += buc2[col[x]], buc1[col[x]] ++; }
void add2 ( const int x ) { cur += buc1[col[x]], buc2[col[x]] ++; }
void sub1 ( const int x ) { cur -= buc2[col[x]], buc1[col[x]] --; }
void sub2 ( const int x ) { cur -= buc1[col[x]], buc2[col[x]] --; }
void captainMO () {
int nowl = 0, nowr = 0;
for ( int i = 1; i <= m; ++ i ) {
for ( ; nowl < asq[i].l; add1 ( ++ nowl ) ) ;
for ( ; nowr < asq[i].r; add2 ( ++ nowr ) ) ;
for ( ; nowl > asq[i].l; sub1 ( nowl -- ) ) ;
for ( ; nowr > asq[i].r; sub2 ( nowr -- ) ) ;
ans[asq[i].ID] += cur * asq[i].x;
}
}
int main () {
n = rint (); int _waste_ = rint ();
for ( int i = 1; i <= n; ++ i ) a[i] = pri[i] = rint ();
for ( int i = 1; i < n; ++ i ) {
int u = rint (), v = rint ();
addE ( u, v ), addE ( v, u );
}
initial (), rt = 1;
for ( int i = 1; i <= _waste_; ++ i ) {
int c = rint (), x, y;
if ( c == 1 ) rt = rint ();
else x = rint (), y = rint (), transASmany ( x, y );
}
sort ( asq + 1, asq + 1 + m, existcmp ), captainMO ();
for ( int i = 1; i <= freq; ++ i ) wint ( ans[i] ), putchar ( '\n' );
return 0;
}
Solution -「洛谷 P4689」「YunoOI 2016」这是我自己的发明的更多相关文章
- 「区间DP」「洛谷P1043」数字游戏
「洛谷P1043」数字游戏 日后再写 代码 /*#!/bin/sh dir=$GEDIT_CURRENT_DOCUMENT_DIR name=$GEDIT_CURRENT_DOCUMENT_NAME ...
- 「 洛谷 」P2768 珍珠项链
珍珠项链 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 题目来源 「 洛谷 」P2768 珍珠项链 ...
- 「 洛谷 」P4539 [SCOI2006]zh_tree
小兔的话 推荐 小兔的CSDN [SCOI2006]zh_tree 题目限制 内存限制:250.00MB 时间限制:1.00s 标准输入输出 题目知识点 思维 动态规划 \(dp\) 区间\(dp\) ...
- 「 洛谷 」P2151 [SDOI2009]HH去散步
小兔的话 欢迎大家在评论区留言哦~ HH去散步 题目限制 内存限制:125.00MB 时间限制:1.00s 标准输入 标准输出 题目知识点 动态规划 \(dp\) 矩阵 矩阵乘法 矩阵加速 矩阵快速幂 ...
- Solution -「JSOI 2019」「洛谷 P5334」节日庆典
\(\mathscr{Description}\) Link. 给定字符串 \(S\),求 \(S\) 的每个前缀的最小表示法起始下标(若有多个,取最小的). \(|S|\le3\time ...
- Solution -「洛谷 P4372」Out of Sorts P
\(\mathcal{Description}\) OurOJ & 洛谷 P4372(几乎一致) 设计一个排序算法,设现在对 \(\{a_n\}\) 中 \([l,r]\) 内的元素排 ...
- Solution -「POI 2010」「洛谷 P3511」MOS-Bridges
\(\mathcal{Description}\) Link.(洛谷上这翻译真的一言难尽呐. 给定一个 \(n\) 个点 \(m\) 条边的无向图,一条边 \((u,v,a,b)\) 表示从 ...
- Solution -「APIO 2016」「洛谷 P3643」划艇
\(\mathcal{Description}\) Link & 双倍经验. 给定 \(n\) 个区间 \([a_i,b_i)\)(注意原题是闭区间,这里只为方便后文描述),求 \(\ ...
- 「P4994」「洛谷11月月赛」 终于结束的起点(枚举
题目背景 终于结束的起点终于写下句点终于我们告别终于我们又回到原点…… 一个个 OIer 的竞赛生涯总是从一场 NOIp 开始,大多也在一场 NOIp 中结束,好似一次次轮回在不断上演.如果这次 NO ...
- 「洛谷4197」「BZOJ3545」peak【线段树合并】
题目链接 [洛谷] [BZOJ]没有权限号嘤嘤嘤.题号:3545 题解 窝不会克鲁斯卡尔重构树怎么办??? 可以离线乱搞. 我们将所有的操作全都存下来. 为了解决小于等于\(x\)的操作,那么我们按照 ...
随机推荐
- 一篇文章带你详细了解axios的封装
axios 封装 对请求的封装在实际项目中是十分必要的,它可以让我们统一处理 http 请求.比如做一些拦截,处理一些错误等.本篇文章将详细介绍如何封装 axios 请求,具体实现的功能如下 基本配置 ...
- Galaxy 生信平台(二):生产环境部署
在 上一篇文章中,我们介绍了适合单个用户进行使用和开发的 Galaxy 在线平台,今天我们来聊一下在为多用户生产环境设置 Galaxy 时,我们应采取的一些可以让 Galaxy 获得最佳性能的额外步骤 ...
- 使用yaml进行数据驱动
一.需求描述 1.请求登陆接口,从登陆接口的响应头数据中获取token值,并写入yml文件: 2.读取写入yml文件中的token值作为下个接口的传参,请求查询物料列表接口,查看查询结果. yaml_ ...
- easyexce报错BeanMap$Generator
class net.sf.cglib.core.DebuggingClassWriter overrides final method visit 这两个报错都可以在一起解决,因为这是由于Jar包冲突 ...
- 基于Sa-Token实现微服务之前的单点登录
修改配置文件,准备好四个域名 127.0.0.1 auth.server.com 127.0.0.1 user.server.com 127.0.0.1 third.server.com 127.0. ...
- 痞子衡嵌入式:从功耗测试角度了解i.MXRTxxx系列片内SRAM分区电源控制
大家好,我是痞子衡,是正经搞技术的痞子.今天痞子衡给大家介绍的是从功耗测试角度了解i.MXRTxxx系列片内SRAM分区电源控制. 我们知道配合 MCU 一起工作的存储器包含 ROM(Flash) 和 ...
- LLaMA模型指令微调 字节跳动多模态视频大模型 Valley 论文详解
Valley: Video Assistant with Large Language model Enhanced abilitY 大家好,我是卷了又没卷,薛定谔的卷的AI算法工程师「陈城南」~ 担 ...
- Nginx使用Lua脚本加解密RSA字符串
本文主要介绍使用Lua脚本对采用RSA加密后的字符串进行解密的过程. 使用第三方类库lua-resty-rsa,参考地址:https://github.com/spacewander/lua-rest ...
- 2023郑州轻工业大学校赛邀请赛wh
在这里,很感谢程立老师的帮助和选择我,我以后会跟着程老师,既然热爱,就要走下去! 2022年4月2号,我代表河南工业大学与郑州17所高校在郑州轻工业大学举办的"卓见杯"郑州轻工业大 ...
- C语言基础--数组详细说明
目录 一.什么是数组 二.一维数组 1.一维数组创建 2.一维数组的使用 2.1 索引值 2.2 遍历数组 2.3 如何使用sizeof()计算出数组的长度 三.二维数组 1.二维数组的创建 2.二维 ...