树链剖分练习总结
T1 洛谷p3384树链剖分模板
题目大意:1 区间加 2 区间和 3子树加 4子树和
代码:
#include<cstdio> #include<iostream> using namespace std; const int maxn=500005; typedef long long LL; int n,m,u,v,t,r,sumedge,temp; LL mod; int head[maxn],son[maxn],dad[maxn],top[maxn],heavy_son[maxn]; int id[maxn],real[maxn],depth[maxn],a[maxn]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn]; struct segment_tree{ LL l,r,sum,tag; }tr[maxn]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void dfs1(int k,int fa){ dad[k]=fa;depth[k]=depth[fa]+1; son[k]=1; for(int i=head[k];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=fa){ dfs1(v,k); son[k]+=son[v]; if(!heavy_son[k]||son[heavy_son[k]]<son[v]) heavy_son[k]=v; } } } void dfs2(int k,int fir){ top[k]=fir;id[k]=++temp; real[temp]=k; if(!heavy_son[k])return; dfs2(heavy_son[k],fir); for(int i=head[k];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[k]&&v!=heavy_son[k]) dfs2(v,v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; } void pushdown(int rt){ tr[rt<<1].tag+=tr[rt].tag; tr[rt<<1].sum+=tr[rt].tag*(tr[rt<<1].r-tr[rt<<1].l+1); tr[rt<<1|1].tag+=tr[rt].tag; tr[rt<<1|1].sum+=tr[rt].tag*(tr[rt<<1|1].r-tr[rt<<1|1].l+1); tr[rt].tag=0; return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=a[real[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } void update(int now,int ll,int rr,int x){ if(ll<=tr[now].l&&tr[now].r<=rr){ tr[now].sum+=(tr[now].r-tr[now].l+1)*x; tr[now].tag+=x; return; } pushdown(now); int mid=(tr[now].l+tr[now].r)>>1; if(rr<=mid)update(now<<1,ll,rr,x); else if(ll>mid)update(now<<1|1,ll,rr,x); else { update(now<<1,ll,mid,x); update(now<<1|1,mid+1,rr,x); } pushup(now);//*** } LL query_sum(int now,int ll,int rr){ if(ll<=tr[now].l&&tr[now].r<=rr){ return tr[now].sum; } pushdown(now); int mid=(tr[now].l+tr[now].r)>>1; if(rr<=mid)return query_sum(now<<1,ll,rr); else if(ll>mid)return query_sum(now<<1|1,ll,rr); else{ return query_sum(now<<1,ll,mid)+query_sum(now<<1|1,mid+1,rr); } } void change(int u,int v,LL x){ int tu=top[u],tv=top[v]; while(tu!=tv){ if(depth[tu]<depth[tv]){ swap(tu,tv);swap(u,v); } update(1,id[tu],id[u],x); u=dad[tu]; tu=top[u]; } if(depth[u]>depth[v])swap(u,v); update(1,id[u],id[v],x); } int find_sum(int u,int v){ LL sum=0; int tu=top[u],tv=top[v]; while(tu!=tv){ if(depth[tu]<depth[tv]){ swap(tu,tv); swap(u,v); } sum+=query_sum(1,id[tu],id[u]); sum%=mod; u=dad[tu]; tu=top[u]; } if(depth[u]>depth[v])swap(u,v); sum+=query_sum(1,id[u],id[v]); return sum%mod; } void root_add(int now,LL x){ int begin=id[now]; int ed=id[now]+son[now]-1; update(1,begin,ed,x); } LL root_sum(int now){ int begin=id[now]; int ed=id[now]+son[now]-1; return query_sum(1,begin,ed)%mod; } int main(){ scanf("%d%d%d%lld",&n,&m,&r,&mod); for(int i=1;i<=n;i++)scanf("%d",&a[i]); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); add(u,v);add(v,u); } dfs1(r,0);dfs2(r,r); build(1,1,temp); for(int i=0;i<m;i++){ int t,x,y,z; scanf("%d",&t); if(t==1){ scanf("%d%d%d",&x,&y,&z); change(x,y,z); }else if(t==2){ scanf("%d%d",&x,&y); printf("%lld\n",find_sum(x,y)); }else if(t==3){ scanf("%d%d",&x,&y); root_add(x,y); }else if(t==4){ scanf("%d",&x); printf("%lld\n",root_sum(x)); } } return 0; }
#include<iostream> #include<cstdio> #include<cstring> #include<algorithm> #define N 100009 using namespace std; int n,m,r,p,cnt,sumedge; int head[N],size[N],deep[N],dad[N],top[N],tpos[N],a[N],b[N]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[N<<2]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } struct Tree{ int l,r,sum,s; }tr[N<<2]; void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0;tpos[x]=++cnt;b[cnt]=a[x]; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=s&&v!=dad[x])dfs_(v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; return ; } void pushdown(int rt){ tr[rt<<1].sum=(tr[rt<<1].sum%p+(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s%p)%p; tr[rt<<1].s+=tr[rt].s; tr[rt<<1|1].sum=(tr[rt<<1|1].sum%p+(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s%p)%p; tr[rt<<1|1].s+=tr[rt].s; tr[rt].s=0; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=b[l]; return ; } int mid=(l+r)>>1; build(rt<<1,l,mid); build(rt<<1|1,mid+1,r); pushup(rt); } void change(int rt,int l,int r,int ql,int qr,int z){ if(l>=ql&&r<=qr){ tr[rt].sum+=(r-l+1)*z; tr[rt].s+=z; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change(rt<<1,l,mid,ql,qr,z); if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,z); pushup(rt); } int query_sum(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].sum%p; } pushdown(rt); int ans=0,mid=(l+r)>>1; if(ql<=mid)ans=(ans%p+query_sum(rt<<1,l,mid,ql,qr)%p)%p; if(qr>mid)ans=(ans%p+query_sum(rt<<1|1,mid+1,r,ql,qr)%p)%p; return ans; } void add_(int x,int y,int z){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change(1,1,n,tpos[top[y]],tpos[y],z); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change(1,1,n,tpos[x],tpos[y],z); } int query(int x,int y){ int ret=0; for(;top[x]!=top[y];){ if(deep[top[y]]<deep[top[x]])swap(x,y); ret=(ret%p+query_sum(1,1,n,tpos[top[y]],tpos[y])%p)%p; y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); ret=(ret%p+query_sum(1,1,n,tpos[x],tpos[y])%p)%p; return ret; } int main(){ scanf("%d%d%d%d",&n,&m,&r,&p); 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); add(x,y);add(y,x); } dfs(r);dfs_(r);build(1,1,n); for(int i=1;i<=m;i++){ int od,x,y,z; scanf("%d",&od); if(od==1){ scanf("%d%d%d",&x,&y,&z); add_(x,y,z); } if(od==2){ scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); } if(od==3){ scanf("%d%d",&x,&z); change(1,1,n,tpos[x],tpos[x]+size[x]-1,z); } if(od==4){ scanf("%d",&x); printf("%d\n",query_sum(1,1,n,tpos[x],tpos[x]+size[x]-1)); } } return 0; }
T2codevs4633[Mz]树链剖分练习
题目大意:区间加 区间和
代码:
#include<iostream> #include<cstring> #include<cstdio> #define maxn 500008 using namespace std; int n,q,sumedge,cnt; int head[maxn],dad[maxn],top[maxn],deep[maxn],size[maxn],tpos[maxn]; struct Tree{ int l,r,sum,s; }tr[maxn<<2]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; return; } void pushdown(int rt){ if(!tr[rt].s)return; tr[rt<<1].s+=tr[rt].s;tr[rt<<1].sum+=(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s; tr[rt<<1|1].s+=tr[rt].s;tr[rt<<1|1].sum+=(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s; tr[rt].s=0;return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r)return; int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); return; } int query_sum(int rt,int l,int r,int ql,int qr){ pushdown(rt); if(l>=ql&&r<=qr){ return tr[rt].sum; } int ans=0,mid=(l+r)>>1; if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr); if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr); return ans; } void change(int rt,int l,int r,int ql,int qr){ pushdown(rt); if(l>=ql&&r<=qr){ tr[rt].sum+=(tr[rt].r-tr[rt].l+1); tr[rt].s++; return; } int mid=(l+r)>>1; if(ql<=mid)change(rt<<1,l,mid,ql,qr); if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr); pushup(rt); } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0;tpos[x]=++cnt; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } int lca(int x,int y){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); y=dad[top[y]]; } if(deep[x]>deep[y])return y; return x; } void query(int x,int y){ int ret=0; for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); ret+=query_sum(1,1,n,tpos[x],tpos[y]); printf("%d\n",ret); } void change_(int x,int y){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change(1,1,n,tpos[top[y]],tpos[y]); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change(1,1,n,tpos[x],tpos[y]); } int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs(1);dfs_(1);build(1,1,n); scanf("%d",&q); for(int i=1;i<=q;i++){ int a,b,c; scanf("%d%d%d",&a,&b,&c); if(a==1)change_(b,c); else query(b,c); } return 0; } AC
T3洛谷P2590树的统计
题目大意:单点修改 区间和 区间最大值
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100005 #define inf 100000000 using namespace std; int n,q,cnt,sumedge; int w[maxn],size[maxn],deep[maxn],top[maxn],dad[maxn]; int re[maxn],head[maxn],tpos[maxn]; struct Tree{ int l,r,sum,mx; }tr[maxn<<2]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x; dfs(v); size[x]+=size[v]; } } void dfs_(int x){ tpos[x]=++cnt;re[cnt]=x; int s=0; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx); return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=tr[rt].mx=w[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } void update(int rt,int l,int r,int q,int v){ if(l==r){ tr[rt].sum=tr[rt].mx=v; return; } int mid=(l+r)>>1; if(q<=mid)update(rt<<1,l,mid,q,v); else update(rt<<1|1,mid+1,r,q,v); pushup(rt); } int querysum(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return tr[rt].sum; int mid=(l+r)>>1,ans=0; if(ql<=mid)ans+=querysum(rt<<1,l,mid,ql,qr); if(qr>mid)ans+=querysum(rt<<1|1,mid+1,r,ql,qr); return ans; } int querymax(int rt,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr)return tr[rt].mx; int mid=(l+r)>>1,ans=-inf; if(ql<=mid)ans=max(ans,querymax(rt<<1,l,mid,ql,qr)); if(qr>mid)ans=max(ans,querymax(rt<<1|1,mid+1,r,ql,qr)); return ans; } int qsum(int x,int y){ int ans=0; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); ans+=querysum(1,1,n,tpos[top[x]],tpos[x]); x=dad[top[x]]; } if(deep[x]>deep[y])swap(x,y); ans+=querysum(1,1,n,tpos[x],tpos[y]); return ans; } int qmax(int x,int y){ int ans=-inf; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); ans=max(ans,querymax(1,1,n,tpos[top[x]],tpos[x])); x=dad[top[x]]; } if(deep[x]>deep[y])swap(x,y); ans=max(ans,querymax(1,1,n,tpos[x],tpos[y])); return ans; } int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } for(int i=1;i<=n;i++)scanf("%d",&w[i]); dfs(1);dfs_(1);build(1,1,n); scanf("%d",&q); for(;q;q--){ int x,y;char s[10]; scanf("%s%d%d",s,&x,&y); if(s[1]=='H')update(1,1,n,tpos[x],y); if(s[1]=='M')printf("%d\n",qmax(x,y)); if(s[1]=='S')printf("%d\n",qsum(x,y)); } return 0; }
T4BZOJ4034树上操作
题目大意:区间修改 子树和 节点到根节点的路径权值和
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 500005 #define LL long long using namespace std; int sumedge,cnt,n,m; int head[maxn],size[maxn],dad[maxn],deep[maxn],top[maxn]; int tpos[maxn],re[maxn],w[maxn]; struct Tree{ int l,r;LL sum,s; }tr[maxn<<2]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void read(int &x){ char ch=getchar();x=0;int f=1; for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-1; for(;isdigit(ch);ch=getchar())x=x*10+ch-'0'; x=x*f; } void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0;tpos[x]=++cnt;re[cnt]=x; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum; return; } void pushdown(int rt){ if(!tr[rt].s)return; tr[rt<<1].s+=tr[rt].s;tr[rt<<1|1].s+=tr[rt].s; tr[rt<<1].sum+=(LL)(tr[rt<<1].r-tr[rt<<1].l+1)*tr[rt].s; tr[rt<<1|1].sum+=(LL)(tr[rt<<1|1].r-tr[rt<<1|1].l+1)*tr[rt].s; tr[rt].s=0;return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=w[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } void change(int rt,int l,int r,int ql,int qr,int p){ if(l>=ql&&r<=qr){ tr[rt].sum+=(LL)(r-l+1)*p; tr[rt].s+=p; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change(rt<<1,l,mid,ql,qr,p); if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p); pushup(rt); } LL query_sum(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].sum; } pushdown(rt); int mid=(l+r)>>1;LL ans=0; if(ql<=mid)ans+=query_sum(rt<<1,l,mid,ql,qr); if(qr>mid)ans+=query_sum(rt<<1|1,mid+1,r,ql,qr); return ans; } LL query(int x){ LL ret=0; for(;top[x]!=1;){ ret+=query_sum(1,1,n,tpos[top[x]],tpos[x]); x=dad[top[x]]; } ret+=query_sum(1,1,n,1,tpos[x]); return ret; } int main(){ read(n);read(m); for(int i=1;i<=n;i++)read(w[i]); for(int i=1;i<n;i++){ int x,y; read(x);read(y); add(x,y);add(y,x); } dfs(1);dfs_(1);build(1,1,n); for(int i=1;i<=m;i++){ int od,x,a; read(od);read(x); if(od==1){ read(a); change(1,1,n,tpos[x],tpos[x],a); }else if(od==2){ read(a); change(1,1,n,tpos[x],tpos[x]+size[x]-1,a); }else if(od==3){ printf("%lld\n",query(x)); } } return 0; } AC
T5BZOJ2243染色
题目大意:求a-b路径上有多少个颜色连续的序列
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 100009 using namespace std; int n,m,cnt,sumedge; int head[maxn],dad[maxn],size[maxn],deep[maxn],top[maxn]; int c[maxn],re[maxn],tpos[maxn]; char s[10]; struct Tree{ int l,r,sum,lc,rc,s; }tr[maxn<<2]; struct Edge{ int x,y,nxt; Edge(int x=0,int y=0,int nxt=0): x(x),y(y),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y){ edge[++sumedge]=Edge(x,y,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0;tpos[x]=++cnt;re[cnt]=x; if(!top[x])top[x]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].sum=tr[rt<<1].sum+tr[rt<<1|1].sum-(tr[rt<<1].rc==tr[rt<<1|1].lc); tr[rt].lc=tr[rt<<1].lc;tr[rt].rc=tr[rt<<1|1].rc; return; } void pushdown(int rt){ if(!tr[rt].s)return; tr[rt<<1].sum=tr[rt<<1|1].sum=1; tr[rt<<1].rc=tr[rt<<1].lc=tr[rt<<1|1].lc=tr[rt<<1|1].rc=tr[rt].s; tr[rt<<1].s=tr[rt<<1|1].s=tr[rt].s; tr[rt].s=0;return; } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r; if(l==r){ tr[rt].sum=1;tr[rt].lc=tr[rt].rc=c[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } void change(int rt,int l,int r,int ql,int qr,int p){ if(l>=ql&&r<=qr){ tr[rt].sum=1;tr[rt].lc=tr[rt].rc=p;tr[rt].s=p; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change(rt<<1,l,mid,ql,qr,p); if(qr>mid)change(rt<<1|1,mid+1,r,ql,qr,p); pushup(rt); } int query_sum(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].sum; } pushdown(rt); int mid=(l+r)>>1; if(qr<=mid)return query_sum(rt<<1,l,mid,ql,qr); if(ql>mid)return query_sum(rt<<1|1,mid+1,r,ql,qr); return query_sum(rt<<1,l,mid,ql,qr)+query_sum(rt<<1|1,mid+1,r,ql,qr)-(tr[rt<<1].rc==tr[rt<<1|1].lc);//** } int getcolr(int rt,int l,int r,int p){ if(l==r)return tr[rt].lc; pushdown(rt); int mid=(l+r)>>1; if(p<=mid)return getcolr(rt<<1,l,mid,p); if(p>mid)return getcolr(rt<<1|1,mid+1,r,p); } int query(int x,int y){ int ret=0; for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); ret+=query_sum(1,1,n,tpos[top[y]],tpos[y]); if(getcolr(1,1,n,tpos[top[y]])==getcolr(1,1,n,tpos[dad[top[y]]]))ret--; y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); ret+=query_sum(1,1,n,tpos[x],tpos[y]); return ret; } void change_(int x,int y,int c){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change(1,1,n,tpos[top[y]],tpos[y],c); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change(1,1,n,tpos[x],tpos[y],c); } int main(){ scanf("%d%d",&n,&m); for(int i=1;i<=n;i++)scanf("%d",&c[i]); for(int i=1;i<n;i++){ int x,y; scanf("%d%d",&x,&y); add(x,y);add(y,x); } dfs(1);dfs_(1);build(1,1,n); for(int i=1;i<=m;i++){ int x,y,z; scanf("%s",s); if(s[0]=='Q'){ scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); }else { scanf("%d%d%d",&x,&y,&z); change_(x,y,z); } } return 0; } AC
T6BZOJ1984月下毛景树
题目大意:
Max x--y 树上x--y之间边的最大权值
Cover x--y w.树上x--y之前边的权值都变为w
Add x--y w 树上x--y之间边权都加w
Change x w把第x条边权值改为w
代码:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 300009 using namespace std; int n,m,cnt,sumedge; int size[maxn],dad[maxn],deep[maxn],top[maxn],head[maxn]; int tpos[maxn],re[maxn],fe[maxn],st[maxn],ed[maxn]; char s[10]; struct Tree{ int l,r,mx,adc,cvs; }tr[maxn<<2]; struct Edge{ int x,y,z,nxt; Edge(int x=0,int y=0,int z=0,int nxt=0): x(x),y(y),z(z),nxt(nxt){} }edge[maxn<<1]; void add(int x,int y,int z){ edge[++sumedge]=Edge(x,y,z,head[x]); head[x]=sumedge; } void dfs(int x){ size[x]=1;deep[x]=deep[dad[x]]+1; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v==dad[x])continue; dad[v]=x;fe[v]=edge[i].z;dfs(v); size[x]+=size[v]; } } void dfs_(int x){ int s=0; if(!top[x])top[x]=x; tpos[x]=++cnt;re[cnt]=x; for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&size[v]>size[s])s=v; } if(s){ top[s]=top[x]; dfs_(s); } for(int i=head[x];i;i=edge[i].nxt){ int v=edge[i].y; if(v!=dad[x]&&v!=s)dfs_(v); } } void pushup(int rt){ tr[rt].mx=max(tr[rt<<1].mx,tr[rt<<1|1].mx); return; } void pushdown(int rt){ if(tr[rt].cvs!=-1){ tr[rt<<1].mx=tr[rt<<1|1].mx=tr[rt].cvs; tr[rt<<1].adc=tr[rt<<1|1].adc=0; tr[rt<<1].cvs=tr[rt<<1|1].cvs=tr[rt].cvs; tr[rt].cvs=-1; } if(tr[rt].adc){ tr[rt<<1].mx+=tr[rt].adc;tr[rt<<1|1].mx+=tr[rt].adc; tr[rt<<1].adc+=tr[rt].adc;tr[rt<<1|1].adc+=tr[rt].adc; tr[rt].adc=0; } } void build(int rt,int l,int r){ tr[rt].l=l;tr[rt].r=r;tr[rt].cvs=-1; if(l==r){ tr[rt].mx=fe[re[l]]; return; } int mid=(l+r)>>1; build(rt<<1,l,mid);build(rt<<1|1,mid+1,r); pushup(rt); } //----------------------------------------------------- void change_Node(int rt,int l,int r,int p,int w){ if(l==r){ tr[rt].mx=w; return; } pushdown(rt); int mid=(l+r)>>1; if(p<=mid)change_Node(rt<<1,l,mid,p,w); if(p>mid)change_Node(rt<<1|1,mid+1,r,p,w); pushup(rt); } void change_node(int k,int w){ int p,x,y; x=st[k];y=ed[k];p=dad[x]==y?x:y; change_Node(1,1,n,tpos[p],w); } //-------------------------------------------------------- void change_Cover(int rt,int l,int r,int ql,int qr,int w){ if(l>=ql&&r<=qr){ tr[rt].mx=w;tr[rt].cvs=w;tr[rt].adc=0; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change_Cover(rt<<1,l,mid,ql,qr,w); if(qr>mid)change_Cover(rt<<1|1,mid+1,r,ql,qr,w); pushup(rt); } void change_cover(int x,int y,int w){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change_Cover(1,1,n,tpos[top[y]],tpos[y],w); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change_Cover(1,1,n,tpos[x]+1,tpos[y],w); } //--------------------------------------------------------- void change_Add(int rt,int l,int r,int ql,int qr,int w){ if(l>=ql&&r<=qr){ tr[rt].mx+=w;tr[rt].adc+=w; return; } pushdown(rt); int mid=(l+r)>>1; if(ql<=mid)change_Add(rt<<1,l,mid,ql,qr,w); if(qr>mid)change_Add(rt<<1|1,mid+1,r,ql,qr,w); pushup(rt); } void change_add(int x,int y,int w){ for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); change_Add(1,1,n,tpos[top[y]],tpos[y],w); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); change_Add(1,1,n,tpos[x]+1,tpos[y],w); } //----------------------------------------------------------- int query_mx(int rt,int l,int r,int ql,int qr){ if(l>=ql&&r<=qr){ return tr[rt].mx; } pushdown(rt); int mid=(l+r)>>1,ret=-1; if(ql<=mid)ret=max(ret,query_mx(rt<<1,l,mid,ql,qr)); if(qr>mid)ret=max(ret,query_mx(rt<<1|1,mid+1,r,ql,qr)); return ret; } int query(int x,int y){ int ans=-1; for(;top[x]!=top[y];){ if(deep[top[x]]>deep[top[y]])swap(x,y); ans=max(ans,query_mx(1,1,n,tpos[top[y]],tpos[y])); y=dad[top[y]]; } if(deep[x]>deep[y])swap(x,y); ans=max(ans,query_mx(1,1,n,tpos[x]+1,tpos[y])); return ans; } //------------------------------------------------------------ int main(){ scanf("%d",&n); for(int i=1;i<n;i++){ int z; scanf("%d%d%d",&st[i],&ed[i],&z); add(st[i],ed[i],z);add(ed[i],st[i],z); } dfs(1);dfs_(1);build(1,1,n); while(1){ int x,y,z; scanf("%s",s); if(s[0]=='S')break; if(s[1]=='h'){ scanf("%d%d",&x,&z); change_node(x,z); }else if(s[1]=='o'){ scanf("%d%d%d",&x,&y,&z); change_cover(x,y,z); }else if(s[1]=='d'){ scanf("%d%d%d",&x,&y,&z); change_add(x,y,z); }else if(s[2]=='x'){ scanf("%d%d",&x,&y); printf("%d\n",query(x,y)); } } return 0; } AC