bzoj 4765: 普通计算姬
Description
Input
Output
Sample Input
0 0 3 4 0 1
0 1
1 2
2 3
2 4
3 5
5 6
2 1 2
1 1 1
2 3 6
2 3 5
Sample Output
10
9
HINT
Source
感受到树上分块的邪恶力量!!! %%%XLightGod;
貌似这题有很多种做法,主要是连续编号的子树和不是很好搞!!!
直接讲树上分块的做法好了,不想绕圈子:
子树和依据我们以前打树链剖分的时候(其实应该叫轻重链剖分,今天听到了一位NOI金牌爷说了个叫长链剖分的鬼玩意);
我们知道一个点的子树其实就是一段连续的dfs序;
首先对[1,n]分块,想到分块查询的基本思想
那么每次询问相当与是若干个整块加上剩下的几个点;
我们一步一步来解决:
首先对于每一个块的可以通过统计每个点在子树中出现的次数,那么我们可以通过O(n)的时间计算出整块贡献;
接下来的瓶颈就在于解决如何快速O(1)求出每个点的子树和
根据子树是dfs序中连续的一段我们可以考虑对dfs序进行分块,然后统计所有块的前缀和以及每个块自己内部的前缀和,通过前缀和的基本操作可以O(1)求解
附上代码:
- // MADE BY QT666
- #include<cstdio>
- #include<algorithm>
- #include<cmath>
- #include<iostream>
- #include<queue>
- #include<set>
- #include<cstdlib>
- #include<cstring>
- #include<string>
- #include<ctime>
- #define lson num<<1
- #define rson num<<1|1
- using namespace std;
- typedef long long ll;
- const int N=100001;
- int gi()
- {
- int x=0,flag=1;
- char ch=getchar();
- while(ch<'0'||ch>'9'){if(ch=='-') flag=-1;ch=getchar();}
- while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
- return x*flag;
- }
- int head[N],to[N*2],nxt[N*2];
- int v[N],pos[N],kp[N],dfn[N],id[N],block,num[320][N],fa[N],end[N];
- int n,m,cnt,tt,cnt2,root;
- unsigned long long tot1[N],tot2[320],tot3[320];
- void dfs(int x,int f){
- dfn[x]=++tt;id[tt]=x;
- for(int i=head[x];i;i=nxt[i]){
- int y=to[i];
- if(y!=f){
- fa[y]=x;dfs(y,x);
- }
- }
- end[x]=tt;
- }
- inline void lnk(int x,int y){
- to[++cnt]=y,nxt[cnt]=head[x],head[x]=cnt;
- to[++cnt]=x,nxt[cnt]=head[y],head[y]=cnt;
- }
- unsigned long long query(int x){return tot3[pos[x]-1]+tot1[x];}
- inline void make_tot1(){
- for(int i=1;i<=n;i++) tot1[dfn[i]]=v[i];
- for(int i=1;i<=n;i++) {if(kp[i]!=1) tot1[i]+=tot1[i-1];}
- }
- inline void make_tot2(){
- for(int i=1;i<=cnt2;i++)
- for(int j=1;j<=n;j++)
- num[i][id[j]]=num[i][fa[id[j]]]+(pos[id[j]]==i);
- for(int i=1;i<=cnt2;i++)
- for(int j=1;j<=n;j++)
- tot2[i]+=(unsigned long long)1ll*num[i][j]*v[j];
- }
- inline void make_tot3(){
- for(int i=1;i<=n;i++) tot3[pos[dfn[i]]]+=v[i];
- for(int i=1;i<=cnt2;i++) tot3[i]+=tot3[i-1];
- }
- int main()
- {
- freopen("1.in","r",stdin);
- freopen("1.out","w",stdout);
- n=gi(),m=gi();int x,y;
- for(int i=1;i<=n;i++) v[i]=gi();
- for(int i=1;i<=n;i++){
- x=gi(),y=gi();
- if(x!=0) lnk(x,y);
- else root=y;
- }
- int block=sqrt(n);
- if(n%block) cnt2=n/block+1;
- else cnt2=n/block;
- for(int i=1;i<=n;i++){
- pos[i]=(i-1)/block+1;
- kp[i]=(i-1)%block+1;
- }
- dfs(root,0);
- make_tot1();make_tot2();make_tot3();int flag;
- while(m--){
- flag=gi();
- if(flag==1){
- x=gi(),y=gi()-v[x];
- for(int i=dfn[x];i<=n&&pos[i]==pos[dfn[x]];i++) tot1[i]+=y;
- for(int i=1;i<=cnt2;i++) tot2[i]+=(unsigned long long)1ll*num[i][x]*y;
- for(int i=pos[dfn[x]];i<=cnt2;i++) tot3[i]+=y;
- v[x]+=y;
- }
- else{
- int l=gi(),r=gi();unsigned long long ans=0;
- if(pos[l]==pos[r]){
- for(int i=l;i<=r;i++)
- ans+=query(end[i])-query(dfn[i]-1);
- }
- else{
- for(int i=l;pos[i]==pos[l];i++) ans+=query(end[i])-query(dfn[i]-1);
- for(int i=r;pos[i]==pos[r];i--) ans+=query(end[i])-query(dfn[i]-1);
- for(int i=pos[l]+1;i<pos[r];i++) ans+=tot2[i];
- }
- printf("%llu\n",ans);
- }
- }
- return 0;
- }
bzoj 4765: 普通计算姬的更多相关文章
- BZOJ 4765 普通计算姬 (分块 + BIT)
4765: 普通计算姬 Time Limit: 30 Sec Memory Limit: 256 MBSubmit: 1547 Solved: 329[Submit][Status][Discus ...
- bzoj 4765 普通计算姬 dfs序 + 分块
题目链接 Description "奋战三星期,造台计算机".小G响应号召,花了三小时造了台普通计算姬.普通计算姬比普通计算机要厉害一些.普通计算机能计算数列区间和,而普通计算姬能 ...
- bzoj 4765: 普通计算姬 主席树+替罪羊树思想
题目大意: 给定一棵\(n\)个节点的带权树有根树,设\(sum_p\)表示以点\(p\)为根的这棵子树中所有节点的权 计算姬支持下列两种操作: 给定两个整数\(u,v\),修改点\(u\)的权值为\ ...
- bzoj 4765 普通计算姬(树状数组 + 分块)
http://www.lydsy.com/JudgeOnline/problem.php?id=4765 很nice的一道题啊(可能是因为卡了n久终于做出来了 题意就是给你一棵带点权的有根树,sum( ...
- BZOJ 4765 普通计算姬 dfs序+分块+树状数组+好题!!!
真是道好题...感到灵魂的升华... 按dfs序建树状数组,拿前缀和去求解散块: 按点的标号分块,分成一个个区间,记录区间子树和 的 总和... 具体地,需要记录每个点u修改后,对每一个块i的贡献,记 ...
- BZOJ 4765: 普通计算姬 [分块 树状数组 DFS序]
传送门 题意: 一棵树,支持单点修改和询问以$[l,r]$为根的子树的权值和的和 只有我这种不会分块的沙茶不会做这道题吗? 说一点总结: 子树和当然上$dfs$序了,询问原序列一段区间所有子树和,对原 ...
- BZOJ 4765: 普通计算姬 (分块+树状数组)
传送门 解题思路 树上的分块题,,对于修改操作,每次修改只会对他父亲到根这条链上的元素有影响:对于查询操作,每次查询[l,r]内所有元素的子树,所以就考虑dfn序,进标记一次,出标记一次,然后子树就是 ...
- bzoj 4766: 文艺计算姬 -- 快速乘
4766: 文艺计算姬 Time Limit: 1 Sec Memory Limit: 128 MB Description "奋战三星期,造台计算机".小W响应号召,花了三星期 ...
- BZOJ 4766: 文艺计算姬
4766: 文艺计算姬 Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 456 Solved: 239[Submit][Status][Discuss] ...
随机推荐
- Dynamics 365创建电子邮箱字段包含值的联系人同时更改负责人的方法。
摘要: 本人微信和易信公众号: 微软动态CRM专家罗勇 ,回复267或者20171129可方便获取本文,同时可以在第一间得到我发布的最新的博文信息,follow me!我的网站是 www.luoyon ...
- 面试相关-转载-well,yzl——持续更新
转载yl,yzl大神的面经,顺便自己复习一下专业课的内容 操作系统相关: 什么是进程, 什么是线程.它们之间的区别和联系. 进程管理内存资源+运行过程, 线程只管理运行过程, 线程要在进程提供的资源基 ...
- Android UsageStatsService(应用使用统计服务)的学习与调研
一. 简介 UsageStatsService是一个系统服务,其主要通过AMS等,来监测并记录各个应用的使用数据,如上次调用com.android.settings的时间等. UsageStatsSe ...
- Beautifulsoup分解
from urllib.request import Request, ProxyHandler from urllib.request import build_opener from bs4 im ...
- hibernate第一天
首先介绍一下javaEE开发的三层架构 Web层 也被称为表现层 它是表现层的一个设计模型:也就是大家常用的MVC开发模式 Service层 它是和需求相关的 DAO层 它只和数据 ...
- Neutron控制节点集群
#Neutron控制节点集群 openstack pike 部署 目录汇总 http://www.cnblogs.com/elvi/p/7613861.html #.Neutron控制节点集群 #本实 ...
- C#使用Xamarin开发可移植移动应用终章(11.获取设备信息与常用组件,开源一个可开发模版.)
前言 系列目录 C#使用Xamarin开发可移植移动应用目录 源码地址:https://github.com/l2999019/DemoApp 可以Star一下,随意 - - 说点什么.. 本系列,终 ...
- python2.6升级2.7
1.下载Python-2.7.3 #wget http://python.org/ftp/python/2.7.3/Python-2.7.3.tar.bz2 2.解压 #tar -jxvf Pyt ...
- 程序员的自我救赎---3.1:理解Oauth2.0
<前言> (一) Winner2.0 框架基础分析 (二)PLSQL报表系统 (三)SSO单点登录 (四) 短信中心与消息中心 (五)钱包系统 (六)GPU支付中心 (七)权限系统 (八) ...
- c++简单编写线性表(实验)
哇 好久没更博客了 因为从上次更文到现在为止,我一直在学c#,然后也觉得没什么太大的东西想写在博客上, 总之这次就简单的传一下学校安排的数据结构的实验,我还是学生,是新手,希望能继续跟大家一起学习, ...