【分块】铃铛计数问题
应该算分块的好题,因为我没想到
题目
求树上∑i=lrsi\sum_{i=l}^rs_i∑i=lrsi,其中sis_isi表示子树权值和,带修
题解
O(nn)O(n\sqrt n)O(nn)
分块,一个维护原标号,一个维护dfndfndfn序
修改时,更改第一种块需要用到dpi,kdp_{i,k}dpi,k表示iii标号会在第kkk块中计算几次。用第二种块维护散点权值,将原本单点修改变为区间修改单点查,依次做到之后查询O(1)O(1)O(1)
查询时,第一种块爆加,散块在第二种块里查
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int N=1e5+10,M=2*N,K=4e2+10;
int n,q;
int head[N],nex[M],to[M],tot;
void build(int u,int v){tot++;nex[tot]=head[u];to[tot]=v;head[u]=tot;}
//
int g,sq;
int bl[N],L[N],R[N];
ll a[N],s[N],b[N];
ll ak[K],bk[K];int dp[N][K];
int dfn[N],sz[N],cnt;
void init()
{sq=sqrt(n);for(int i=1;i<=n;i++){if((i-1)%sq==0)R[g]=i-1,L[++g]=i;bl[i]=g;}R[g]=n;
}
void add(int l,int r,ll key)
{int x=bl[l],y=bl[r];if(y-x<=2){for(int i=l;i<=r;i++)b[i]+=key;return ;}for(int i=l;i<=R[x];i++)b[i]+=key;x++;for(int i=L[y];i<=r;i++)b[i]+=key;y--;for(int i=x;i<=y;i++)bk[i]+=key;
}
ll qur(int u)
{int x=dfn[u]-1,y=dfn[u]+sz[u]-1;return (b[y]+bk[bl[y]])-(b[x]+bk[bl[x]]);
}
ll qur2(int l,int r)
{int x=bl[l],y=bl[r];ll tmp=0;if(y-x<=2){for(int i=l;i<=r;i++)tmp+=qur(i);return tmp;}for(int i=l;i<=R[x];i++)tmp+=qur(i);x++;for(int i=L[y];i<=r;i++)tmp+=qur(i);y--;for(int i=x;i<=y;i++)tmp+=ak[i];return tmp;
}
void dfs(int u,int f)
{dfn[u]=++cnt;b[cnt]=a[u];sz[u]=1;s[u]=a[u];for(int i=1;i<=g;i++)dp[u][i]=dp[f][i]+(L[i]<=u&&u<=R[i]);for(int i=head[u];i;i=nex[i]){int v=to[i];if(v==f)continue;dfs(v,u);sz[u]+=sz[v];s[u]+=s[v];}ak[bl[u]]+=s[u];
}
signed main()
{scanf("%d%d",&n,&q);n++;init();for(int i=2;i<=n;i++)scanf("%d",&a[i]);for(int x,y,i=1;i<n;i++){scanf("%d%d",&x,&y);x++;y++;build(x,y);build(y,x);}dfs(1,0);for(int i=1;i<=n;i++)b[i]+=b[i-1];for(int op,x,y,i=1;i<=q;i++){scanf("%d%d%d",&op,&x,&y);x++;if(op==1){for(int j=1;j<=g;j++)ak[j]+=(ll)dp[x][j]*(y-a[x]);add(dfn[x],cnt,(ll)y-a[x]);a[x]=y;}else printf("%lld\n",qur2(x,y+1));}
}
【分块】铃铛计数问题相关推荐
- 铃铛计数问题 解题报告
U72118 铃铛计数问题 对点我们发现有两种编号,一种是它本身的编号用作询问,一种是便于我们子树/链的操作的重新编号. 如果对链树剖作为第二编号,把点放到二维平面内,我们就可以用个kd-tree维护 ...
- 铃铛计数问题——分块
题目 [题目描述] 圣诞节来了,仓鼠又要来策划活动了,今年仓鼠会在圣诞树上挂上铃铛! 已知圣诞树有 $n$ 个节点,并且根节点是固定的.记 $s[i]$ 表示以 $i$ 为根的子树中,所有节点上铃铛数 ...
- #4258. 铃铛计数问题
题意 内存限制:256 MiB 时间限制:2000 ms 圣诞节来了,仓鼠又要来策划活动了,今年仓鼠会在圣诞树上挂上铃铛! 已知圣诞树有 nnn 个节点,并且根节点是固定的.记 s[i]s[i]s[i ...
- 【学习笔记】无向图、有向图的三元环、四元环计数问题(根号分支+bitset)
三元环计数和四元环计数问题 无向图三元环计数问题 根号分治 bitset 无向图四元环计数问题 有向图三四元环计数问题 无向图三元环计数问题 根号分治 记 di:id_i:idi:i 在原图中的度数 ...
- java 二分搜索获得大于目标数的第一位_程序员常用查找算法(顺序、二分、插值、分块、斐波那契)...
顺序查找 基本思想 属于线性查找和无序查找,从一端开始顺序扫描,直到找到与目标值value相等的元素. 这是最基本的查找方法,也是时间复杂度最高的查找算法. 在数据过多时,这种方法并不适用. 代码实现 ...
- 数据库 大数据访问及分区分块优化方案
本文导读:当系统要满足每秒数万次的读写请求的需求时,我们可以用分布式计算.编写优良的程序代码.对海量数据进行分区操作.建立广泛的索引.建立缓存机制.加大虚拟内存.分批处理.使用数据仓库和多维数据库存储 ...
- OpenCV 【一】—— OpenCV中数组指针、图像分块计算、指针取像素值与MatToEigen方法,内存对齐
{ Topic1: 高效开辟内存,使适用于大型数组.//开辟新数组,或者开辟新的0或者某一数值的数组/Mat或者Map直接使用memset //大数组操作效率较高 举例1:cv::Mat cv_ncc ...
- GDAL中GDALDataset::RasterIO分块读取的实现
GDALDataset类中的RasterIO函数能够对图像任意指定区域.任意波段的数据按指定数据类型.指定排列方式读入内存和写入文件中,因此可以实现对大影像的分块读.写运算操作.针对特大的影像图像,有 ...
- python分块处理功能_Python-numpy实现灰度图像的分块和合并方式
我就废话不多说了,直接上代码吧! from numpy import * import numpy as np import cv2, os, math, os.path from PIL impor ...
最新文章
- Field、CopyField、DynamicField的一些简介,用法
- c++实现websocket服务端与JavaScript通讯
- Unity Gamma校正转为线性空间
- android listview左滑删除
- input发送a.jax_JAX-RS 2.0的新功能– @BeanParam批注
- flask mysql分页,Flask分页的实现方法
- icd植入是大手术吗_骨折手术植入了钢板,骨折痊愈后,需要取出钢板吗?
- UIScrollView无法滚动
- 连接access时的REGDB_E_CLASSNOTREG(0x80040154)错误
- 三角传输的在链路均衡项目中的灵活应用
- [译]发布ABP v0.19包含Angular UI选项
- JavaEE Design Patter(2)
- Python selenium报错:selenium.common.exceptions.ElementClickInterceptedException
- openFeign服务调用
- uni-app开发开发h5,小程序,app,注意事项
- 分享在工作生活中更好地运用思维导图使用攻略
- 3DMax 2014中文版安装破解教程
- 香帅的北大金融学课笔记18 -- 监管、创新、危机
- 2020电子设计竞赛G题 - 非接触物体尺寸形态测量
- Intel IPP密码库 IPPCP 2018——第二部分 对称密码算法开发说明与示例代码