【bzoj3052】[wc2013]糖果公园 带修改树上莫队
题目描述
给出一棵n个点的树,每个点有一个点权,点权范围为1~m。支持两种操作:(1)修改一个点的点权 (2)对于一条路径,求$\sum\limits_{i=1}^m\sum\limits_{j=1}^{s_i}V_iW_j$,其中$s_i$表示这条链上权值为i的点数。
输入
.jpg)
输出
.jpg)
样例输入
4 3 5
1 9 2
7 6 5 1
2 3
3 1
3 4
1 2 3 2
1 1 2
1 4 2
0 2 1
1 1 2
1 4 2
样例输出
84
131
27
84
题解
带修改树上莫队
带修改树上莫队——普通莫队的 带修改进化版+上树树上进化版。
带修改莫队:每块大小$n^{\frac 23}$,分别以左端点所在块、右端点所在块、时间(这次询问之前的修改次数)为第一、二、三关键字排序,然后暴力移动三个指针。
树上莫队:分块方法改成树分块(树分块方法参考 王室联邦),自然序改成DFS序(然而带修改莫队用不到自然序,这里只是提一嘴),暴力移动指针。这里可以把点权加到边权上(链上LCA只在统计答案是算上),以避免特判。
把它们结合起来本题就做完了。把树分块,然后按照带修改莫队处理即可。
几点注意:
求LCA要用非朴素LCA(因为不仅仅在移动指针时需要求LCA,点权加到边权上时统计答案也需要处理LCA)
修改要记录是从什么改到什么,因为有反向修改(时间指针左移)操作。
答案会爆int,故需要long long。
时间复杂度$O(n^{\frac 53})$
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 100010
using namespace std;
const int b = 1200;
typedef long long ll;
int v[N] , w[N] , head[N] , to[N << 1] , next[N << 1] , ce , type[N];
int fa[N][20] , deep[N] , log[N] , tot , sta[N] , top , bl[N] , num;
int pc[N] , wc[N] , vc[N] , vis[N] , cnt[N];
ll ans , ret[N];
struct data
{
int lp , rp , cp , id;
bool operator<(const data &a)const
{
return bl[lp] == bl[a.lp] ? bl[rp] == bl[a.rp] ? cp < a.cp : bl[rp] < bl[a.rp] : bl[lp] < bl[a.lp];
}
}a[N];
void add(int x , int y)
{
to[++ce] = y , next[ce] = head[x] , head[x] = ce;
}
void dfs(int x)
{
int i , now = top;
for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(i = head[x] ; i ; i = next[i])
{
if(to[i] != fa[x][0])
{
fa[to[i]][0] = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
if(top - now >= b)
{
num ++ ;
while(top != now) bl[sta[top -- ]] = num;
}
}
}
sta[++top] = x;
}
int lca(int x , int y)
{
int i;
if(deep[x] < deep[y]) swap(x , y);
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if(deep[x] - deep[y] >= (1 << i))
x = fa[x][i];
if(x == y) return x;
for(i = log[deep[x]] ; ~i ; i -- )
if(deep[x] >= (1 << i) && fa[x][i] != fa[y][i])
x = fa[x][i] , y = fa[y][i];
return fa[x][0];
}
void rev(int x)
{
if(vis[x]) ans -= (ll)w[cnt[type[x]]] * v[type[x]] , cnt[type[x]] -- , vis[x] = 0;
else cnt[type[x]] ++ , ans += (ll)w[cnt[type[x]]] * v[type[x]] , vis[x] = 1;
}
int main()
{
int n , m , q , i , j , x , y , opt , cc = 0 , ln = 1 , rn = 1 , now = 0;
scanf("%d%d%d" , &n , &m , &q);
for(i = 1 ; i <= m ; i ++ ) scanf("%d" , &v[i]);
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &w[i]);
for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , log[i] = log[i >> 1] + 1;
dfs(1);
while(top) bl[sta[top -- ]] = num;
for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &type[i]);
for(i = 1 ; i <= q ; i ++ )
{
scanf("%d" , &opt);
if(opt)
{
scanf("%d%d" , &a[i - cc].lp , &a[i - cc].rp) , a[i - cc].cp = cc , a[i - cc].id = i - cc;
if(bl[a[i - cc].lp] > bl[a[i - cc].rp]) swap(a[i - cc].lp , a[i - cc].rp);
}
else cc ++ , scanf("%d%d" , &pc[cc] , &vc[cc]) , wc[cc] = type[pc[cc]] , type[pc[cc]] = vc[cc];
}
for(i = cc ; i ; i -- ) type[pc[i]] = wc[i];
sort(a + 1 , a + q - cc + 1);
for(i = 1 ; i <= q - cc ; i ++ )
{
x = lca(ln , a[i].lp);
for(j = ln ; j != x ; j = fa[j][0]) rev(j);
for(j = a[i].lp ; j != x ; j = fa[j][0]) rev(j);
x = lca(rn , a[i].rp);
for(j = rn ; j != x ; j = fa[j][0]) rev(j);
for(j = a[i].rp ; j != x ; j = fa[j][0]) rev(j);
ln = a[i].lp , rn = a[i].rp , x = lca(ln , rn) , rev(x);
while(now < a[i].cp)
{
now ++ ;
if(vis[pc[now]]) cnt[vc[now]] ++ , ans += (ll)w[cnt[vc[now]]] * v[vc[now]] - (ll)w[cnt[wc[now]]] * v[wc[now]] , cnt[wc[now]] -- ;
type[pc[now]] = vc[now];
}
while(now > a[i].cp)
{
if(vis[pc[now]]) cnt[wc[now]] ++ , ans += (ll)w[cnt[wc[now]]] * v[wc[now]] - (ll)w[cnt[vc[now]]] * v[vc[now]] , cnt[vc[now]] -- ;
type[pc[now]] = wc[now];
now -- ;
}
ret[a[i].id] = ans;
rev(x);
}
for(i = 1 ; i <= q - cc ; i ++ ) printf("%lld\n" , ret[i]);
return 0;
}
【bzoj3052】[wc2013]糖果公园 带修改树上莫队的更多相关文章
- 【bzoj4129】Haruna’s Breakfast 带修改树上莫队+分块
题目描述 给出一棵树,点有点权.支持两种操作:修改一个点的点权,查询链上mex. 输入 第一行包括两个整数n,m,代表树上的结点数(标号为1~n)和操作数.第二行包括n个整数a1...an,代表每个结 ...
- 【BZOJ3052】[wc2013]糖果公园 带修改的树上莫队
[BZOJ3052][wc2013]糖果公园 Description Input Output Sample Input Sample Input Sample Output 84 131 27 84 ...
- bzoj 3052: [wc2013]糖果公园 带修改莫队
3052: [wc2013]糖果公园 Time Limit: 250 Sec Memory Limit: 512 MBSubmit: 506 Solved: 189[Submit][Status] ...
- UOJ 58 (树上带修改的莫队)
UOJ 58 糖果公园 Problem : 给一棵n个点的树,每个点上有一种颜色,对于一条路径上的点,若 i 颜色第 j 次出现对该路径权值的贡献为 w[i] * c[j], 每次询问一条路径的权值, ...
- 【BZOJ】2120: 数颜色 带修改的莫队算法
[题意]给定n个数字,m次操作,每次询问区间不同数字的个数,或修改某个位置的数字.n,m<=10^4,ai<=10^6. [算法]带修改的莫队算法 [题解]对于询问(x,y,t),其中t是 ...
- BZOJ 2120: 数颜色 带修改的莫队算法 树状数组套主席树
https://www.lydsy.com/JudgeOnline/problem.php?id=2120 标题里是两种不同的解法. 带修改的莫队和普通莫队比多了个修改操作,影响不大,但是注意一下细节 ...
- P1903 [国家集训队]数颜色 / 维护队列 带修改的莫队
\(\color{#0066ff}{ 题目描述 }\) 墨墨购买了一套N支彩色画笔(其中有些颜色可能相同),摆成一排,你需要回答墨墨的提问.墨墨会向你发布如下指令: 1. Q L R代表询问你从第L支 ...
- UVA - 12345 带修改的莫队
题意显然:给出初始序列,单点修改,区间查询元素的种类. 由于时限过宽,暴力可过. 比较优秀的解法应该是莫队. 带修改的莫队题解可以看https://www.luogu.org/blog/user126 ...
- codeforces 940F 带修改的莫队
F. Machine Learning time limit per test 4 seconds memory limit per test 512 megabytes input standard ...
随机推荐
- webpack3构建全面提速优化vue-cli
前言 伴随着vue的全球化,各种vue的组件框架越来越完善,从早期的element-ui到vux,iview等越来越多高质量的项目,使用vue进行前端构建已然是一件工程化,模块化,敏捷化的事情 在这其 ...
- MIP组件开发 自定义js组件开发步骤
什么是百度MIP? MIP(Mobile Instant Pages - 移动网页加速器)主要用于移动端页面加速 官网参考:https://www.mipengine.org/doc/00-mip-1 ...
- Dynamics 365-下载新版本的开发工具
可以使用下面的Powershell脚本在NuGet下載最新的CRM开发工具.这些工具包括: Tool NuGet Package Code generation tool CrmSvcUtil.exe ...
- java.lang.UnsupportedOperationException: seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed
错误描述: ElasticSearch集群启动错误,错误的原因是:因为Centos6不支持SecComp,而ES默认bootstrap.system_call_filter为true进行检测,所以导致 ...
- Python正则表达式-基础
Python正则表达式-基础 本文转载自昔日暖阳,原文地址:http://www.osheep.cn/4806.html python使用正则,需要先引入re模块 import re 匹配符 单个字符 ...
- Java学习笔记四:Java的八种基本数据类型
Java的八种基本数据类型 Java语言提供了八种基本类型.六种数字类型(四个整数型,两个浮点型),一种字符类型,还有一种布尔型. Java基本类型共有八种,基本类型可以分为三类,字符类型char,布 ...
- SEARCH(文字の検索)
文字列に関する無効命令 以下の各命令は無効であり.4.6 および 6.10 までのリリースとの互換性を確保するためにのみ利用可能となっています.これらの命令が古いプログラムの中に出現することはあります ...
- SQLServer 将日期改造成标准日期格式(如: 2016/6 ->201606)
同事给了份Excel 数据,导到数据库之后再查出来时发现顺序不好弄.于是想从数据源中做处理. 由于数据存在,年/月 与 年/月/日 的格式不好用datetime保存,于是用varchar保存. 数据处 ...
- python2.7练习小例子(十一)
11):题目:判断101-200之间有多少个素数,并输出所有素数. 程序分析:判断素数的方法:用一个数分别去除2到sqrt(这个数),如果能被整除,则表明此数不是素数,反之是素数. ...
- [答网友问]让GridLength支持动画
原文:[答网友问]让GridLength支持动画 [答网友问]WPF中让GridLength类型支持动画 ...