洛谷試煉場 4-17 樹鏈剖分
阿新 • • 發佈:2019-02-10
putchar ptree lin ret down class with size 包管理
layout: post
title: 洛谷試煉場 4-17 樹鏈剖分
author: "luowentaoaa"
catalog: true
mathjax: true
tags:
- 樹鏈剖分
- 數據結構
- 洛谷
[ZJOI2008]樹的統計 (入門題,鏈最大值,鏈和)
思路
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int maxn=1e6+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int n,q,a[maxn]; vector<int>G[maxn]; int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn]; int id[maxn],pre[maxn],cnt=0; void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } int sumv[maxn<<2],maxv[maxn<<2]; inline void pushup(int o){ sumv[o]=sumv[o<<1]+sumv[o<<1|1]; maxv[o]=max(maxv[o<<1],maxv[o<<1|1]); } void build(int o,int l,int r){ int mid=(l+r)/2; if(l==r){ sumv[o]=maxv[o]=a[pre[l]];return; } build(o<<1,l,mid);build(o<<1|1,mid+1,r); pushup(o); } void update(int o,int l,int r,int q,int v){ int mid=(l+r)/2; if(l==r){ sumv[o]=maxv[o]=v;return; } if(q<=mid)update(o<<1,l,mid,q,v); else update(o<<1|1,mid+1,r,q,v); pushup(o); } int querysum(int o,int l,int r,int ql,int qr){ int mid=(l+r)/2,ans=0; if(ql<=l&&r<=qr)return sumv[o]; if(ql<=mid)ans+=querysum(o<<1,l,mid,ql,qr); if(qr>mid)ans+=querysum(o<<1|1,mid+1,r,ql,qr); return ans; } int querymax(int o,int l,int r,int ql,int qr){ int mid=(l+r)/2,ans=-inf; if(ql<=l&&r<=qr)return maxv[o]; if(ql<=mid)ans=max(ans,querymax(o<<1,l,mid,ql,qr)); if(qr>mid)ans=max(ans,querymax(o<<1|1,mid+1,r,ql,qr)); return ans; } int qsum(int u,int v){ int ans=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans+=querysum(1,1,n,id[top[u]],id[u]); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); ans+=querysum(1,1,n,id[v],id[u]); return ans; } int qmax(int u,int v){ int ans=-inf; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); ans=max(ans,querymax(1,1,n,id[top[u]],id[u])); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); ans=max(ans,querymax(1,1,n,id[v],id[u])); return ans; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); cin>>n; for(int i=1;i<n;i++){ int u,v; cin>>u>>v;G[u].push_back(v);G[v].push_back(u); } for(int i=1;i<=n;i++)cin>>a[i]; fa[1]=1;dfs1(1,0,1);dfs2(1,1);build(1,1,n); int q; cin>>q; while(q--){ int x,y;char s[100]; cin>>s>>x>>y; if(s[1]=='H')update(1,1,n,id[x],y); else if(s[1]=='M')cout<<qmax(x,y)<<endl; else if(s[1]=='S')cout<<qsum(x,y)<<endl; } return 0; }
[P2486 SDOI2011]染色 (區間操作很難 未AC)
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int maxn=1e6+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int n,q,col[maxn]; vector<int>G[maxn]; int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn]; int id[maxn],pre[maxn],cnt=0; void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } struct node{ int l,r; int num,lazy,lc,rc; }my[maxn<<2]; void push_up(int o){ my[o].lc=my[o<<1].lc;my[o].rc=my[(o<<1)|1].rc; int ans=my[o<<1].num+my[(o<<1)|1].num; if(my[o<<1].rc==my[(o<<1)|1].lc)ans--; my[o].num=ans; } void push_down(int o){ if(my[o].lazy){ my[o<<1].lazy=my[(o<<1)|1].lazy=my[o].lazy; my[o<<1].num=my[(o<<1)|1].num=1; my[o<<1].lc=my[o<<1].rc=my[o].lc; my[(o<<1)|1].lc=my[(o<<1)|1].rc=my[o].lc; my[o<<1].lazy=0; } } void build(int o,int l,int r){ int mid=(l+r)/2; my[o].l=l;my[o].r=r;my[o].num=0;my[o].lazy=0; if(l==r){ my[o].num=1; my[o].lc=my[o].rc=col[pre[l]]; return; } build(o<<1,l,mid);build((o<<1)|1,mid+1,r); push_up(o); } void update(int o,int l,int r,int x){ if(my[o].l==l&&my[o].r==r){ my[o].num=my[o].lazy=1; my[o].lc=my[o].rc=x; return; } push_down(o); int mid=(my[o].l+my[o].r)/2; if(r<=mid)update(o<<1,l,r,x); else if(l>mid)update((o<<1)|1,l,r,x); else{ update(o<<1,l,mid,x);update((o<<1)|1,mid+1,r,x); } push_up(o); } void uptree(int u,int v,int c){ while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v); update(1,id[top[u]],id[u],c); u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v); update(1,id[v],id[u],c); } int lc,rc; int query(int o,int l,int r,int L,int R){ if(my[o].l==L)lc=my[o].lc; if(my[o].r==R)rc=my[o].rc; if(my[o].l==l&&my[o].r==r)return my[o].num; push_down(o); int mid=(my[o].l+my[o].r)/2; if(r<=mid)return query(o<<1,l,r,L,R); else if(l>mid)return query((o<<1)|1,l,r,L,R); else{ int ans=query(o<<1,l,mid,L,R); ans+=query((o<<1)|1,mid+1,r,L,R); if(my[o<<1].rc==my[(o<<1)|1].lc)ans--; return ans; } push_up(o); } int qutree(int u,int v){ int ans1=-1,ans2=-1,ans=0; while(top[u]!=top[v]){ if(dep[top[u]]<dep[top[v]])swap(u,v),swap(ans1,ans2); ans+=query(1,id[top[u]],id[u],id[top[u]],id[u]); if(rc==ans1)ans--; ans1=lc;u=fa[top[u]]; } if(dep[u]<dep[v])swap(u,v),swap(ans1,ans2); ans+=query(1,id[v],id[u],id[v],id[u]); if(rc==ans1)ans--; if(lc==ans2)ans--; return ans; } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); int m; cin>>n>>m; for(int i=1;i<=n;i++)cin>>col[i]; for(int i=1;i<n;i++){ int u,v;cin>>u>>v; G[u].push_back(v);G[v].push_back(u); } dfs1(1,1,1);dfs2(1,1);build(1,1,n); while(m--){ char s[150]; cin>>s; int x,y; if(s[0]=='C'){ int c;cin>>x>>y>>c; uptree(x,y,c); } else{ cin>>x>>y; cout<<qutree(x,y)<<endl; } } return 0; }
[P2146 NOI2015]軟件包管理器
#include<bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=998244353; const int maxn=1e6+50; const ll inf=0x3f3f3f3f3f3f3f3fLL; int n,q,col[maxn]; vector<int>G[maxn]; int size[maxn],son[maxn],fa[maxn],dep[maxn],top[maxn]; int id[maxn],pre[maxn],cnt=0; void dfs1(int u,int f,int deep){ size[u]=1; fa[u]=f;son[u]=0;dep[u]=deep; for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==f)continue; dfs1(v,u,deep+1); size[u]+=size[v]; if(size[v]>size[son[u]])son[u]=v; } } void dfs2(int u,int root){ id[u]=++cnt;top[u]=root;pre[cnt]=u; if(son[u])dfs2(son[u],root); for(int i=0;i<G[u].size();i++){ int v=G[u][i]; if(v==fa[u]||v==son[u])continue; dfs2(v,v); } } int sum[maxn<<2],lazy[maxn<<2]; void push_up(int o){ sum[o]=sum[o<<1]+sum[o<<1|1]; } void push_down(int o,int l,int r){ if(lazy[o]){ int mid=(l+r)/2; if(lazy[o]==-1)sum[o<<1]=sum[o<<1|1]=0,lazy[o<<1]=lazy[o<<1|1]=-1; else sum[o<<1]=mid-l+1,sum[o<<1|1]=r-mid,lazy[o<<1]=lazy[o<<1|1]=1; lazy[o]=0; } } void uninstall(int o,int l,int r,int ql,int qr,int x){ if(ql<=l&&r<=qr){ if(!x)lazy[o]=-1,sum[o]=0; else lazy[o]=1,sum[o]=r-l+1;return; } int mid=(l+r)/2;push_down(o,l,r); if(mid>=ql)uninstall(o<<1,l,mid,ql,qr,x); if(mid<qr)uninstall(o<<1|1,mid+1,r,ql,qr,x); push_up(o); } void install(int v,int x,int y){ while(top[x]!=top[y]){ if(dep[top[x]]<dep[top[y]])swap(x,y); uninstall(1,1,n,id[top[x]],id[x],v); x=fa[top[x]]; } if(dep[x]<dep[y])swap(x,y); uninstall(1,1,n,id[y],id[x],v); } int main() { std::ios::sync_with_stdio(false); std::cin.tie(0); std::cout.tie(0); cin>>n; for(int i=2;i<=n;i++){ int u; cin>>u;u++; G[i].push_back(u); G[u].push_back(i); } dfs1(1,1,1); dfs2(1,1); int m;cin>>m; char op[150]; while(m--){ int x; cin>>op>>x;x++;int p=sum[1]; if(op[0]=='i'){ install(1,x,1); cout<<abs(p-sum[1])<<endl; } else{ uninstall(1,1,n,id[x],id[x]+size[x]-1,0); cout<<abs(p-sum[1])<<endl; } } return 0; } /* 7 0 0 0 1 1 5 5 install 5 install 6 uninstall 1 install 4 uninstall 0 */
[P3258 JLOI2014]松鼠的新家 (區間加減)
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=998244353;
const int maxn=3e5+50;
const ll inf=0x3f3f3f3f3f3f3f3fLL;
vector<int>G[maxn];
int id[maxn],dep[maxn],pre[maxn],fa[maxn],size[maxn],son[maxn],cnt,top[maxn];
void dfs1(int now,int f,int deep){
fa[now]=f;size[now]=1;son[now]=0;dep[now]=deep;
for(auto i:G[now]){
if(i==f)continue;
dfs1(i,now,deep+1);
size[now]+=size[i];
if(size[i]>size[son[now]])son[now]=i;
}
}
void dfs2(int now,int root){
id[now]=++cnt;pre[cnt]=now;top[now]=root;
if(son[now])dfs2(son[now],root);
for(auto i:G[now]){
if(i==fa[now]||i==son[now])continue;
dfs2(i,i);
}
}
int sum[maxn<<2],lazy[maxn<<2];
void push_up(int o){
sum[o]=sum[o<<1]+sum[o<<1|1];
}
void push_down(int o,int l,int r){
if(lazy[o]){
int mid=(l+r)/2;
lazy[o<<1]+=lazy[o];
lazy[o<<1|1]+=lazy[o];
sum[o<<1]+=(mid-l+1)*lazy[o];
sum[o<<1|1]+=(r-mid)*lazy[o];
lazy[o]=0;
}
}
void update(int o,int l,int r,int ql,int qr,int w){
int mid=(l+r)/2;
if(ql<=l&&r<=qr){
lazy[o]+=w;
sum[o]+=(r-l+1)*w;
return;
}
push_down(o,l,r);
if(ql<=mid)update(o<<1,l,mid,ql,qr,w);
if(qr>mid)update(o<<1|1,mid+1,r,ql,qr,w);
push_up(o);
}
void print(int o,int l,int r,int ql,int qr){
cout<<"o=="<<o<<" l="<<l<<" r="<<r<<" ql="<<ql<<" qr="<<qr<<endl;
cout<<"sum="<<sum[o]<<endl;
}
int query(int o,int l,int r,int ql,int qr){
//print(o,l,r,ql,qr);
if(l==r){
return sum[o];
}
int mid=(l+r)/2;
push_down(o,l,r);
if(ql<=mid)return query(o<<1,l,mid,ql,qr);
else return query(o<<1|1,mid+1,r,ql,qr);
}
void uptree(int u,int v,int w){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
update(1,1,cnt,id[top[u]],id[u],w);
u=fa[top[u]];
}
if(dep[u]<dep[v])swap(u,v);
update(1,1,cnt,id[v],id[u],w);
}
int a[maxn];
// 適用於正負整數
template <class T>
inline bool read(T &ret)
{
char c;
int sgn;
if (c = getchar(), c == EOF) return 0; //EOF
while (c != '-' && (c < '0' || c > '9')) c = getchar();
sgn = (c == '-') ? -1 : 1;
ret = (c == '-') ? 0 : (c - '0');
while (c = getchar(), c >= '0' && c <= '9') ret = ret * 10 + (c - '0');
ret *= sgn;
return 1;
}
inline void out(int x)
{
if (x > 9) out(x / 10);
putchar(x % 10 + '0');
}
int main()
{
/* std::ios::sync_with_stdio(false);
std::cin.tie(0);
std::cout.tie(0);*/
int n;
//cin>>n;
read(n);
for(int i=1;i<=n;i++)cin>>a[i];
for(int i=1;i<n;i++){
int u,v;
// cin>>u>>v;
read(u);read(v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs1(1,1,1);dfs2(1,1);
for(int i=1;i<n;i++){
uptree(a[i],a[i+1],1);
uptree(a[i+1],a[i+1],-1);
}
for(int i=1;i<=n;i++){
// cout<<query(1,1,n,id[i],id[i])<<endl;
out(query(1,1,n,id[i],id[i]));
puts("");
}
return 0;
}
洛谷試煉場 4-17 樹鏈剖分