3589: 动态树|树链剖分|线段树
来源:互联网 发布:演唱会软件推荐 编辑:程序博客网 时间:2024/06/13 20:05
直接树链剖分,然后查询一段路径的时候顺便在线段树中打上标记,如果再查到这个地方的时候就直接忽略掉这部分对答案的贡献
#include<algorithm>#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<vector>#include<cmath>#include<queue>#include<ctime>#include<set>#include<map>#define N 800020#define inf 1e9#define pa pair<int,int>using namespace std;int sc(){ int i=0; char c=getchar(); while(c>'9'||c<'0')c=getchar(); while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar(); return i;}const long long mod=2147483648LL;long long sum[N],tag[N];int tim[N],mn[N];int deep[N],fa[N],top[N],size[N];int S[N],T[N];int head[N],nxt[N],lst[N];int n,tot,cnt,Q;void insert(int x,int y){ lst[++tot]=y; nxt[tot]=head[x]; head[x]=tot; lst[++tot]=x; nxt[tot]=head[y]; head[y]=tot;}void dfs1(int x,int f){ size[x]=1; for(int i=head[x];i;i=nxt[i]) if(lst[i]!=f) { fa[lst[i]]=x; deep[lst[i]]=deep[x]+1; dfs1(lst[i],x); size[x]+=size[lst[i]]; }}void dfs2(int x,int htp){ int k=0; top[x]=htp; S[x]=T[x]=++cnt; for(int i=head[x];i;i=nxt[i]) if(lst[i]!=fa[x]&&size[lst[i]]>size[k])k=lst[i]; if(!k)return; dfs2(k,htp); for(int i=head[x];i;i=nxt[i]) if(lst[i]!=fa[x]&&lst[i]!=k) dfs2(lst[i],lst[i]); T[x]=cnt;}void push_down(int x,int l,int mid,int r){ int L=x<<1,R=x<<1|1; if(tag[x]) { tag[L]=(tag[L]+tag[x])%mod; tag[R]=(tag[R]+tag[x])%mod; sum[L]=(sum[L]+tag[x]*(mid-l+1))%mod; sum[R]=(sum[R]+tag[x]*(r-mid))%mod; tag[x]=0; } tim[L]=max(tim[L],mn[x]); tim[R]=max(tim[R],mn[x]); mn[L]=max(mn[L],mn[x]); mn[R]=max(mn[R],mn[x]);}void change(int x,int L,int R,int l,int r,long long delta){ if(L==l&&R==r) { tag[x]=(tag[x]+delta)%mod; sum[x]=(sum[x]+delta*(r-l+1))%mod; return ; } int mid=L+R>>1; push_down(x,L,mid,R); if(r<=mid) change(x<<1,L,mid,l,r,delta); else if(l>mid) change(x<<1|1,mid+1,R,l,r,delta); else change(x<<1,L,mid,l,mid,delta),change(x<<1|1,mid+1,R,mid+1,r,delta); sum[x]=sum[x<<1]+sum[x<<1|1]; //tim[x]=max(tim[x<<1],tim[x<<1|1]);}long long ask(int x,int L,int R,int l,int r,int TI){ int mid=L+R>>1; if(L==l&&R==r) { if(mn[x]==TI)return 0; else if(tim[x]<TI) { mn[x]=tim[x]=TI; return sum[x]; } else { long long ans=ask(x<<1,L,mid,l,mid,TI)+ask(x<<1|1,mid+1,R,mid+1,r,TI); mn[x]=tim[x]=TI; return ans; } } long long ans=0; push_down(x,L,mid,R); if(r<=mid) ans=ask(x<<1,L,mid,l,r,TI); else if(l>mid) ans=ask(x<<1|1,mid+1,R,l,r,TI); else ans=ask(x<<1,L,mid,l,mid,TI)+ask(x<<1|1,mid+1,R,mid+1,r,TI); tim[x]=max(tim[x<<1],tim[x<<1|1]); mn[x]=min(mn[x<<1],mn[x<<1|1]); return ans;}long long query(int x,int y,int TI){ long long ans=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])swap(x,y); ans+=ask(1,1,n,S[top[x]],S[x],TI); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); ans+=ask(1,1,n,S[x],S[y],TI); return ans%mod;}int main(){ n=sc(); for(int i=1;i<n;i++) { int x=sc(),y=sc(); insert(x,y); } dfs1(1,0);dfs2(1,1); Q=sc(); for(int i=1;i<=Q;i++) { int opt=sc(),s; if(opt==0) { int x=sc(),y=sc(); change(1,1,n,S[x],T[x],y); } else { long long ans=0; for(int j=1,s=sc();j<=s;j++) { int x=sc(),y=sc(); ans+=query(x,y,i); } printf("%lld\n",ans%mod); } } return 0;}
0 0
- 3589: 动态树|树链剖分|线段树
- BZOJ 3589: 动态树 树链剖分线段树
- bzoj 3589: 动态树 树链剖分+线段树
- bzoj 3589: 动态树 (树链剖分+线段树)
- A1517. 动态树 树链剖分+线段树
- 【bzoj3589】动态树 树链剖分+线段树
- bzoj 3531(动态加点线段树,树链剖分)
- [BZOJ4712]洪水-树链剖分-动态规划-线段树
- poj2750 线段树+动态规划
- POJ_1769_动态规划+线段树
- 【线段树】动态最值
- 线段树--动态区间查询
- 树链剖分+动态线段树(BZOJ-3531旅行)
- BZOJ 3531 (树链剖分,线段树动态开点)
- bzoj3531 [Sdoi2014]旅行 【树链剖分+线段树动态开点】
- ★【动态规划】【线段树】基站选址
- 【线段树】动态最值 SCOI2006 minmax
- 【BZOJ - 1058续】 动态线段树
- [装载]spark教程
- iOS 图片背景模糊效果
- linqjs的常用方法
- REDSHIFT性能优化-QUERYID-1301108
- ORA-04030: 在尝试分配...字节(...)时进程内存不足的原因分析解决方法
- 3589: 动态树|树链剖分|线段树
- 最小角回归笔记
- XCode快捷键
- ASP.Net MVC开发基础学习笔记(6):Model和Entity Framework
- [ddmlib] 您的主机中的软件中止了一个已建立的连接。 java.io.IOException: 您的主机中的软件中止了一个已建立的连接。
- Android总结 - Fragment
- Android中为图标加上数字--用于未读短信数提醒等
- iOS中堆和栈的区别
- ARP笔记