真是道好题。。。感到灵魂的升华。。。


按dfs序建树状数组,拿前缀和去求解散块;

按点的标号分块,分成一个个区间,记录区间子树和 的 总和。。。

具体地,需要记录每个点u修改后,对每一个块i的贡献,记为t[u][i]

计算思路:dfs时,每到一个新的点,就让++c[其所在块],为了记录每个块中的点出现过几次,就相当于记录这个点 被每一块中的点 包含了几次 , 然后for一遍,记录t[u][i]=c[i]

当修改一个点时,这个块的和+=这个点u对块i的贡献*这个点的变化量,即sum[i]+=t[u][i]*(v-a[u]);

#include<cstdio>
#include<iostream>
#include<cmath>
#define ll unsigned long long
#define R register ll
using namespace std;
const int N=;
inline ll g() {
R ret=,fix=; register char ch; while(!isdigit(ch=getchar())) fix=ch=='-'?-:fix;
do ret=ret*+(ch^); while(isdigit(ch=getchar())); return ret*fix;
}
int n,m,q,T,cnt,num,rt;
int vr[N<<],nxt[N<<],a[N],fir[N],dfn[N],l[N],r[N],c[],t[N][],pos[N];
ll w[N],sum[];
inline void add(int u,int v) {vr[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt;}
inline int lbt(int x) {return x&-x;}
inline void inc(int pos,ll d) {for(;pos<=n;pos+=lbt(pos)) w[pos]+=d;}
inline ll query(int pos) { R ret=;
for(;pos;pos-=lbt(pos))
ret+=w[pos]; return ret;
}
void dfs(int u) { l[u]=++num,++c[pos[u]]; inc(num,a[u]);
for(R i=;i<=pos[n];++i) t[u][i]=c[i];
for(R i=fir[u];i;i=nxt[i]) { R v=vr[i];
if(l[v]) continue; dfs(v);
} r[u]=num,--c[pos[u]];
}
signed main() {
n=g(),q=g(); T=sqrt(n); m=(n%T)?n/T+:n/T;
for(R i=;i<=n;++i) a[i]=g(); for(R i=;i<=n;++i) pos[i]=(i-)/T+;
for(R i=,u,v;i<=n;++i) {u=g(),v=g(); if(!u) rt=v; else add(u,v),add(v,u);}
dfs(rt);
for(R i=;i<=pos[n];++i) for(R j=(i-)*T+,lim=min(i*T,(ll)n);j<=lim;++j) sum[i]+=query(r[j])-query(l[j]-);
for(R i=;i<=q;++i) {
R k=g(),u=g(),v=g();
if(k&) {
inc(l[u],v-a[u]);
for(R i=;i<=pos[n];++i) sum[i]+=1ull*t[u][i]*(v-a[u]);
a[u]=v;
} else { R ret=;
if(pos[u]==pos[v]) for(R i=u;i<=v;++i) ret+=query(r[i])-query(l[i]-);
else {
for(R i=u;i<=pos[u]*T;++i) ret+=query(r[i])-query(l[i]-);
for(R i=(pos[v]-)*T+;i<=v;++i) ret+=query(r[i])-query(l[i]-);
} for(R i=pos[u]+;i<pos[v];++i) ret+=sum[i]; printf("%llu\n",ret);
}
}
}

这题真神仙。。2019.04.23

最新文章

  1. 初步进行vs单元测试
  2. Python之路【第六篇】python基础 之面向对象(一)
  3. Asp.Net MVC&lt;九&gt;:OWIN,关于StartUp.cs
  4. 动态选路、RIP协议&amp;&amp;OSPF协议详解
  5. 使linux服务器默认使用中文字符集zh_CN.UTF-8
  6. [题解]UVa 10891 Game of Sum
  7. Win10安装framework3.5
  8. Python中时间的处理之——timedelta篇
  9. Valgrind使用[转]
  10. 05文件与IO
  11. hdu-5690 All X(快速幂+乘法逆元)
  12. 深入浅出JMS(二)——JMS的组成
  13. POJ1258-Agri-Net-ACM
  14. MSDN 杂志:UI 前沿技术 - WPF 中的多点触控操作事件
  15. Delphi中TApplication详解
  16. 每天一个Linux命令(09)--touch命令
  17. IScroll5不能滑到最底端的解决办法
  18. https://www.cnblogs.com/h2zZhou/p/5440271.html
  19. OZCode
  20. Python小白学习之路(二)—【Pycharm安装与配置】【创建项目】【运算符】【数据类型】

热门文章

  1. JAVA中几个修饰符的作用以及一些相关话题
  2. 窗体控件JFrame的使用
  3. IPv6地址在URL上的格式
  4. ROS Learning-011 beginner_Tutorials (编程) 编写 ROS 话题版的 Hello World 程序(Python版)
  5. win10 requireAdministrator设置开机自启动无效的解决方案
  6. zookeeper生成节点、删除节点 For Java
  7. linux环境安装python
  8. Java_枚举类
  9. [译]Javascript在ASP NET中的运用
  10. Java50道经典习题-程序27 求素数