Solution -「NOI.AC 省选膜你赛」union
题目
题意简述
给定两颗树 \(A,B\),\(A\) 中的任一结点 \(u\) 与 \(B\) 中的任一结点 \(v\) 都有一个关系值 \(f(u,v)\),初始为 \(0\)。再给出 \(q\) 个形如 \(a1,b1,a2,b2,c\) 的操作,表示对于 \(A\) 中路径 \(a1\leftrightarrow b1\) 上的任一结点 \(u\) 和 \(B\) 中路径 \(a2\leftrightarrow b2\) 上的任一结点 \(v\),\(f(u,v)\leftarrow f(u,v)+c\)。求操作完成后所有的 \(f(u,v)\)。
数据规模
设 \(A\) 的结点数 \(n\),\(B\) 的结点数 \(m\)。
\(n,m\le10^4;~q\le5\times10^5\)。
题解
一道有意思的差分题 owo。
首先将 \(A\) 和 \(B\) 分别树链剖分,把结点编号转化为 \(DFN\) 来考虑问题。
形象地,我们把 \(f\) 列成一个表格,第 \(i\) 行第 \(j\) 列的值表示 \(A\) 中 \(DFN\) 为 \(i\) 的结点 \(u\) 和 \(B\) 中 \(DFN\) 为 \(j\) 的结点 \(v\) 的 \(f(u,v)\) 值。如果操作涉及路径的 \(DFN\) 值连续,那么就相当于修改这个表格的一个子矩阵,可以差分做到。推广到一般情况,只需要用树剖取出 \(A\) 中路径所覆盖的若干个 \(DFN\) 区间和 \(B\) 中路径覆盖的若干个 \(DFN\) 区间,暴力地两两配对,修改子矩阵即可。最后前缀和还原表格,就求出每一个 \(f(u,v)\) 啦~
复杂度 \(O(q\log^2n)\)。
代码
#include <cstdio>
#include <vector>
#include <utility>
#define x1 tmpx1
#define y1 tmpy1
#define x2 tmpx2
#define y2 tmpy2
inline int rint () {
int x = 0, f = 1; char s = getchar ();
for ( ; s < '0' || '9' < s; s = getchar () ) f = s == '-' ? -f : f;
for ( ; '0' <= s && s <= '9'; s = getchar () ) x = x * 10 + ( s ^ '0' );
return x * f;
}
template<typename Tp>
inline void wint ( Tp x ) {
if ( x < 0 ) putchar ( '-' ), x = ~ x + 1;
if ( 9 < x ) wint ( x / 10 );
putchar ( x % 10 ^ '0' );
}
const int MAXN = 1e4;
struct TreeSplit {
int n, fa[MAXN + 5], dep[MAXN + 5], son[MAXN + 5], siz[MAXN + 5];
int indx, top[MAXN + 5], dfn[MAXN + 5], ref[MAXN + 5];
std :: vector<int> graph[MAXN + 5];
inline void read () {
n = rint ();
for ( int i = 1, u, v; i < n; ++ i ) {
u = rint (), v = rint ();
graph[u].push_back ( v ), graph[v].push_back ( u );
}
}
inline void DFS1 ( const int u, const int f ) {
dep[u] = dep[fa[u] = f] + ( siz[u] = 1 );
for ( int v: graph[u] ) if ( v ^ f ) {
DFS1 ( v, u ), siz[u] += siz[v];
if ( siz[son[u]] < siz[v] ) son[u] = v;
}
}
inline void DFS2 ( const int u, const int tp ) {
top[ref[dfn[u] = ++ indx] = u] = tp;
if ( son[u] ) DFS2 ( son[u], tp );
for ( int v: graph[u] ) if ( v ^ fa[u] && v ^ son[u] ) DFS2 ( v, v );
}
inline std :: vector<std :: pair<int, int> > getPath ( int u, int v ) {
static std :: vector<std :: pair<int, int> > ret; ret.clear ();
while ( top[u] ^ top[v] ) {
if ( dep[top[u]] < dep[top[v]] ) u ^= v ^= u ^= v;
ret.push_back ( { dfn[top[u]], dfn[u] } ), u = fa[top[u]];
}
if ( dep[u] < dep[v] ) u ^= v ^= u ^= v;
return ret.push_back ( { dfn[v], dfn[u] } ), ret;
}
} T1, T2;
int sum[MAXN + 5][MAXN + 5];
inline void add ( const int x1, const int y1, const int x2, const int y2, const int k ) {
sum[x1][y1] += k, sum[x1][y2 + 1] -= k, sum[x2 + 1][y1] -= k, sum[x2 + 1][y2 + 1] += k;
}
int main () {
T1.read (), T2.read ();
T1.DFS1 ( 1, 0 ), T1.DFS2 ( 1, 1 );
T2.DFS1 ( 1, 0 ), T2.DFS2 ( 1, 1 );
std :: vector<std :: pair<int, int> > pathA, pathB;
for ( int q = rint (), a, b, u, v, k; q --; ) {
a = rint (), b = rint (), u = rint (), v = rint (), k = rint ();
pathA = T1.getPath ( a, b ), pathB = T2.getPath ( u, v );
for ( auto seca: pathA ) for ( auto secb: pathB ) {
add ( seca.first, secb.first, seca.second, secb.second, k );
}
}
for ( int i = 1; i <= T1.n; ++ i ) {
for ( int j = 1; j <= T2.n; ++ j ) {
sum[i][j] += sum[i - 1][j] + sum[i][j - 1] - sum[i - 1][j - 1];
}
}
long long ans = 0;
for ( int i = 1; i <= T1.n; ++ i ) {
for ( int j = 1; j <= T2.n; ++ j ) {
ans ^= 1ll * T1.ref[i] * T2.ref[j] * sum[i][j];
}
}
wint ( ans ), putchar ( '\n' );
return 0;
}
Solution -「NOI.AC 省选膜你赛」union的更多相关文章
- Solution -「NOI.AC 省选膜你赛」T2
这道题就叫 T2 我有什么办法www 题目 题意简述 给定一个字符串 \(s\),其长度为 \(n\),求无序子串对 \((u,v)\) 的个数,其中 \((u,v)\) 满足 \(u,v\) ...
- Solution -「NOI.AC 省选膜你赛」array
题目 题意简述 维护一个长度为 \(n\) 的序列 \(\{a_n\}\),并给出 \(q\) 个操作: 将下标为 \(x\) 的数修改为 \(y\). 给定 \(l,r,k\),求最大的 \(m ...
- Solution -「NOI.AC 省选膜你赛」寄蒜几盒
题目 题意简述 给定一个含有 \(n\) 个顶点的凸多边形( \(n\) 是偶数),对于每一对相对的边(即中间有 \(\frac{n}2-1\) 条其它边),延长它们以将平面分割为多块,并把包含原 ...
- cdcqの省选膜你赛
cdcqの省选膜你赛 比赛当天因为在杠hnoi2016的大数据结构没有参加,今天补了一下.挺好玩的虽然不看一句话题意的话真的卡读题 此生无悔入东方,来世愿生幻想乡 2651. 新史「新幻想史 -现代史 ...
- Solution -「NOI 2021」「洛谷 P7740」机器人游戏
\(\mathcal{Description}\) Link. 自己去读题面叭~ \(\mathcal{Solution}\) 首先,参悟[样例解释 #2].一种暴力的思路即为钦定集合 \ ...
- Solution -「NOI 2020」「洛谷 P6776」超现实树
\(\mathcal{Description}\) Link. 对于非空二叉树 \(T\),定义 \(\operatorname{grow}(T)\) 为所有能通过若干次"替换 \( ...
- Solution -「NOI 模拟赛」彩色挂饰
\(\mathcal{Description}\) 给定一个含 \(n\) 个点 \(m\) 条边的简单无向图,设图中最大点双的大小为 \(s\),则保证 \(s\le6\).你将要用 \(k\) ...
- Solution -「NOI 模拟赛」出题人
\(\mathcal{Description}\) 给定 \(\{a_n\}\),求一个 \(\{b_{n-1}\}\),使得 \(\forall x\in\{a_n\},\exists i,j\ ...
- Solution -「NOI 2016」「洛谷 P1587」循环之美
\(\mathcal{Description}\) Link. 给定 \(n,m,k\),求 \(x\in [1,n]\cap\mathbb N,y\in [1,m]\cap \mathbb ...
随机推荐
- Apache Ant: If 和 Unless
目录 If And Unless If And Unless 从 Ant 1.9.1 起,可以在所有的任务和嵌套的元素上以特别的命名空间添加 if 和 unless 属性. In order to u ...
- java调用redis的多种方式与心得
心得: /** * 心得: * 1.连接方式主要有:直连同步,直连事务,直连管道,直连管道事务,分布式直连同步,分布式直连管道, * 分布式连接池同步,分布式连接池管道:普通连接池同步,普通连接池管道 ...
- spring cloud --- Ribbon 客户端负载均衡 + RestTemplate ---心得【无熔断器】
spring boot 1.5.9.RELEASE spring cloud Dalston.SR1 1.前言 了解了 eureka 服务注册与发现 的3大角色 ,会使用RestTem ...
- 面渣逆袭:Java并发六十问,快来看看你会多少道!
大家好,我是老三,面渣逆袭 继续,这节我们来盘一盘另一个面试必问知识点--Java并发. 这篇文章有点长,四万字,图文详解六十道Java并发面试题.人已经肝麻了,大家可以点赞.收藏慢慢看!扶我起来,我 ...
- 1010day-人口普查系统
1.xiugai.java package com.edu.ia; import java.io.IOException;import java.sql.SQLException; import ja ...
- Natasha 4.0 探索之路系列(三) 基本的动态编译
Natasha 的设计 动态编译 Roslyn 为开发者提供了动态编译的接口, 允许我们以 C# 代码来编写 Emit 或 表达式树生成的程序集, 但是完成一个编译需要诸多步骤, 用户参与的操作也很多 ...
- 集合框架-工具类-JDK5.0特性-函数可变参数
1 package cn.itcast.p4.news.demo; 2 3 public class ParamterDemo { 4 5 public static void main(String ...
- JS、jQuery 刷新 iframe 的方法
1.JavaScript 刷新 iframe 可以使用以下方法: document.getElementById('some_frame_id').contentWindow.location.rel ...
- ☕【Java深层系列】「并发编程系列」让我们一起探索一下CyclicBarrier的技术原理和源码分析
CyclicBarrier和CountDownLatch CyclicBarrier和CountDownLatch 都位于java.util.concurrent这个包下,其工作原理的核心要点: Cy ...
- 多选菜单shell脚本
有 很多方法 可以读取Bash脚本中的用户输入. 但是,允许用户键入输入会带来一些问题. 主要问题是输入验证,您必须在其中考虑所有可能的输入. 解决此问题的一种简单方法是为Bash脚本创建一个多选菜单 ...