【bzoj4034】 HAOI2015 T2 树链剖分+小变形
2015-07-18 19:16
344 查看
这道题其实是个裸裸的树剖,重点在于怎样处理子树加操作,那么我们在建seq序列时,想办法把一颗子树建的连续起来就好了,那么我们就改变以往的顺序,利用dfs,先跑重链,在跑轻链,这样就把子树建到一起了,然后就非常简单了。话说,这道题跟NOI2015D1T2有什么区别么?
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<iostream> #include<algorithm> #define maxn 100010 using namespace std; struct yts { int l,r; long long data,tag; }t[4*maxn]; int to[2*maxn],next[2*maxn],st[maxn],a[maxn]; int dep[maxn],size[maxn],dd[maxn]; int seq[maxn],mx[maxn],pos[maxn],head[maxn],fa[maxn]; int n,m,T,num,id,qwer; bool vis[maxn]; void addedge(int x,int y) { num++;to[num]=y;next[num]=st[x];st[x]=num; } void dfs1(int x) { size[x]=1;dd[x]=0; for (int p=st[x];p;p=next[p]) if (to[p]!=fa[x]) { fa[to[p]]=x;dep[to[p]]=dep[x]+1; dfs1(to[p]); size[x]+=size[to[p]]; if (size[to[p]]>size[dd[x]]) dd[x]=to[p]; } } void dfs2(int x,int f) { head[x]=f;pos[x]=mx[x]=++id;vis[x]=1; if (dd[x]) dfs2(dd[x],f),mx[x]=max(mx[x],mx[dd[x]]); for (int p=st[x];p;p=next[p]) if (!vis[to[p]]) dfs2(to[p],to[p]),mx[x]=max(mx[x],mx[to[p]]); } void build(int i,int l,int r) { t[i].l=l;t[i].r=r; if (l==r) {t[i].data=a[seq[l]];return;} int mid=(l+r)/2; build(i*2,l,mid);build(i*2+1,mid+1,r); t[i].data=t[i*2].data+t[i*2+1].data; } void release(int i) { if (t[i].l==t[i].r) return; if (t[i].tag!=0) { long long d=t[i].tag; t[i*2].tag+=d;t[i*2+1].tag+=d; t[i*2].data+=d*(t[i*2].r-t[i*2].l+1); t[i*2+1].data+=d*(t[i*2+1].r-t[i*2+1].l+1); t[i].tag=0; } } void modify(int i,int l,int r,int x) { if (l<=t[i].l && t[i].r<=r) {t[i].data+=(long long)(t[i].r-t[i].l+1)*x;t[i].tag+=x;return;} release(i); int mid=(t[i].l+t[i].r)/2; if (l<=mid) modify(i*2,l,r,x); if (mid<r) modify(i*2+1,l,r,x); t[i].data=t[i*2].data+t[i*2+1].data; } long long query(int i,int l,int r) { if (l<=t[i].l && t[i].r<=r) return t[i].data; release(i); int mid=(t[i].l+t[i].r)/2; long long ans=0; if (l<=mid) ans+=query(i*2,l,r); if (mid<r) ans+=query(i*2+1,l,r); return ans; } int main() { scanf("%d%d",&n,&T); for (int i=1;i<=n;i++) scanf("%d",&a[i]); for (int i=1;i<n;i++) { int x,y; scanf("%d%d",&x,&y); addedge(x,y); addedge(y,x); } fa[1]=0;dep[1]=0; dfs1(1); dfs2(1,1); for (int i=1;i<=n;i++) seq[pos[i]]=i; build(1,1,n); while (T--) { int op; scanf("%d",&op); if (op==1) { int x,a; scanf("%d%d",&x,&a); modify(1,pos[x],pos[x],a); } if (op==2) { int x,a; scanf("%d%d",&x,&a); modify(1,pos[x],mx[x],a); } if (op==3) { int x; scanf("%d",&x); long long ans=0; while (dep[head[x]]>dep[1]) { ans+=query(1,pos[head[x]],pos[x]);x=fa[head[x]]; } ans+=query(1,pos[1],pos[x]); printf("%lld\n",ans); } } return 0; }
相关文章推荐
- 《大话数据结构》第9章 排序 9.9 快速排序(下)
- HNOI2011 BZOJ2326 数学作业
- 堆和栈的区别!
- HNOI2011 BZOJ2326 数学作业
- [cocos2dx]重要父类——CCNode节点类
- Python脚本访问Greenplum数据库安装指导
- 《大话数据结构》第9章 排序 9.9 快速排序(上)
- 《大话数据结构》第9章 排序 9.8 归并排序(下)
- c++ thread 笔记1
- 外部javascript 方法修改 angularjs 中$rootScope和$scope
- CentOS下源码安装GCC 5.2.0
- 1048. Find Coins (25)
- Gimp RGB 转 CMYK
- 操作系统笔记
- Atalasoft DotImage 10.6 破解
- POJ 2524 Ubiquitous Religions
- 做好每天的规划和总结
- 《大话数据结构》第9章 排序 9.8 归并排序(上)
- Lua_获取文件扩展名
- Ubuntu虚拟机安装