P1505 [國家集訓隊]旅遊 (樹鏈剖分)
傳送門
很明顯是樹鏈剖分,因為是邊權,所以將每個邊權給深度大的那個點可以了,根節點不用賦值,要求最大值和最小值,所以線段樹不包含根節點。因為點是從0編號的,所以父節點和重兒子陣列要初始化。
#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
const int N=200010,inf=0x3f3f3f3f;
int n,m,a[N],b[N],c[N],h[N],e[N<<1],ne[N<<1],w[N<<1],idx,col[N];
void add(int a,int b,int c)
{
e[idx]=b;ne[idx]=h[a];w[idx]=c;h[a]=idx++;
}
struct segtree
{
struct node
{
int l,r,sum,maxx,minn,lzy;
}tr[N<<2];
void pushup(node &rt,node &l,node &r)
{
rt.sum=l.sum+r.sum;
rt.maxx=max(l.maxx,r.maxx);
rt.minn=min(l.minn,r.minn);
}
void pushdown(node &rt,node &l,node &r)
{
if(rt.lzy&1)
{
l.sum*=-1; l.maxx^=l.minn^=l.maxx^=l.minn;l.maxx*=-1;l.minn*=-1;
r.sum*=-1; r.maxx^=r.minn^=r.maxx^=r.minn;r.maxx*=-1;r.minn*=-1;
l.lzy+=rt.lzy;
r.lzy+=rt.lzy;
}
rt.lzy=0;
}
void build(int rt,int l,int r)
{
if(l==r) tr[rt]={l,r,col[l],col[l],col[l],0};
else
{
int mid=l+r>>1;
tr[rt]={l,r};
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
pushup(tr[rt],tr[rt<<1],tr[rt<<1|1]);
}
}
void updata(int rt,int l,int r,int d,int f)
{
if(l<=tr[rt].l&&r>=tr[rt].r)
{
if(f==1)//取相反數
{
tr[rt].sum*=-1;
tr[rt].maxx^=tr[rt].minn^=tr[rt].maxx^=tr[rt].minn;
tr[rt].minn*=-1;tr[rt].maxx*=-1;
tr[rt].lzy++;
}
else tr[rt].maxx=tr[rt].sum=tr[rt].minn=d;//邊權賦值,單點更新
return ;
}
int mid=tr[rt].l+tr[rt].r>>1;
pushdown(tr[rt],tr[rt<<1],tr[rt<<1|1]);
if(l<=mid) updata(rt<<1,l,r,d,f);
if(r>mid) updata(rt<<1|1,l,r,d,f);
pushup(tr[rt],tr[rt<<1],tr[rt<<1|1]);
return ;
}
node query(int rt,int l,int r)
{
if(l<=tr[rt].l&&r>=tr[rt].r) return tr[rt];
int mid=tr[rt].l+tr[rt].r>>1;
pushdown(tr[rt],tr[rt<<1],tr[rt<<1|1]);
if(r<=mid) return query(rt<<1,l,r);
if(l>mid) return query(rt<<1|1,l,r);
node ans,left,right;
left=query(rt<<1,l,r);
right=query(rt<<1|1,l,r);
pushup(ans,left,right);
return ans;
}
}tree;
struct shupo
{
int top[N],dfn[N],son[N],dep[N],sz[N],fa[N],cnt;
void dfs1(int u)
{
sz[u]=1;
for(int i=h[u];i!=-1;i=ne[i])
{
int v=e[i];
if(v==fa[u]) continue;
dep[v]=dep[u]+1;
fa[v]=u;
dfs1(v);
sz[u]+=sz[v];
if(son[u]==-1) son[u]=v;
else if(sz[v]>sz[son[u]]) son[u]=v;
}
}
void dfs2(int u,int t,int c)
{
dfn[u]=++cnt;
col[cnt]=c;
top[u]=t;
for(int i=h[u];i!=-1;i=ne[i])
if(e[i]==son[u])
dfs2(son[u],t,w[i]);
for(int i=h[u];i!=-1;i=ne[i])
{
int v=e[i];
if(v==son[u]||v==fa[u]) continue;
dfs2(v,v,w[i]);
}
}
void updata_ed(int u,int d)
{
if(dep[a[u]]>dep[b[u]]) a[u]^=b[u]^=a[u]^=b[u];
tree.updata(1,dfn[b[u]],dfn[b[u]],d,0);//a[u],b[u]的時間戳不相鄰!!
}
void updata_mem(int x,int y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]]) x^=y^=x^=y;//swap
tree.updata(1,dfn[top[y]],dfn[y],0,1);
y=fa[top[y]];
}
if(dep[x]>dep[y]) x^=y^=x^=y;
if(dfn[x]+1<=dfn[y]) tree.updata(1,dfn[x]+1,dfn[y],0,1);//同一條鏈的時候深度高的那個點表示的邊權不在要更新的路徑上,下同
return ;
}
int query_sum(int x,int y)
{
int ans=0;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]]) x^=y^=x^=y;
ans+=tree.query(1,dfn[top[y]],dfn[y]).sum;
y=fa[top[y]];
}
if(dep[x]>dep[y]) x^=y^=x^=y;
if(dfn[x]+1<=dfn[y]) ans+=tree.query(1,dfn[x]+1,dfn[y]).sum;
return ans;
}
int query_max(int x,int y)
{
int ans=-inf;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]]) x^=y^=x^=y;
ans=max(ans,tree.query(1,dfn[top[y]],dfn[y]).maxx);
y=fa[top[y]];
}
if(dep[x]>dep[y]) x^=y^=x^=y;
if(dfn[x]+1<=dfn[y]) ans=max(ans,tree.query(1,dfn[x]+1,dfn[y]).maxx);
return ans;
}
int query_min(int x,int y)
{
int ans=inf;
while(top[x]!=top[y])
{
if(dep[top[x]]>dep[top[y]]) x^=y^=x^=y;
ans=min(ans,tree.query(1,dfn[top[y]],dfn[y]).minn);
y=fa[top[y]];
}
if(dep[x]>dep[y]) x^=y^=x^=y;
if(dfn[x]+1<=dfn[y]) ans=min(ans,tree.query(1,dfn[x]+1,dfn[y]).minn);
return ans;
}
}T;
int main()
{
memset(h,-1,sizeof h);
memset(T.son,-1,sizeof T.son);
memset(T.fa,-1,sizeof T.fa);
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%d%d%d",a+i,b+i,c+i);
add(a[i],b[i],c[i]);
add(b[i],a[i],c[i]);
}
T.dfs1(0);
T.dfs2(0,0,0);
tree.build(1,2,n);
scanf("%d",&m);
char op[5];
int x,y;
while(m--)
{
scanf("%s%d%d",op,&x,&y);
if(*op=='C') T.updata_ed(x,y);
else if(*op=='N') T.updata_mem(x,y);
else if(*op=='S') printf("%d\n",T.query_sum(x,y));
else if(op[1]=='A') printf("%d\n",T.query_max(x,y));
else printf("%d\n",T.query_min(x,y));
}
return 0;
}
相關文章
- 樹鏈剖分
- [OI] 樹鏈剖分
- 2024.3.14 樹鏈剖分
- 淺談樹鏈剖分
- 樹鏈剖分總結
- Something about 樹鏈剖分
- 【筆記/模板】樹鏈剖分筆記
- #8. 「模板」樹鏈剖分
- [LOJ139]-樹鏈剖分
- [國家集訓隊] Tree I
- 「學習筆記」樹鏈剖分筆記
- 樹鏈剖分學習筆記筆記
- 對樹鏈剖分的愛 題解
- P8025 【樹鏈剖分求祖先】
- 樹鏈剖分模板+入門題 SPOJ - QTREEQT
- 樹鏈剖分解析
- P1501 [國家集訓隊]Tree II
- bzoj4551: [Tjoi2016&Heoi2016]樹(樹鏈剖分)
- 一起來學習樹鏈剖分吧!
- bzoj3531: [Sdoi2014]旅行(樹鏈剖分+線段樹)
- P1407 [國家集訓隊] 穩定婚姻
- [國家集訓隊] Crash的數字表格 / JZPTAB
- 樹剖 dsu on tree 長鏈
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- 長鏈剖分模板
- 省隊集訓遊記
- 長鏈剖分筆記筆記
- 迴文樹線上剖分???
- BF的資料結構題單-提高組——樹鏈剖分資料結構
- 洛谷P1494 [國家集訓隊]小Z的襪子(莫隊)
- 熟練剖分(tree) 樹形DP
- bzoj3626: [LNOI2014]LCA(離線處理+樹鏈剖分)
- 重鏈剖分題目選講
- P2371-[國家集訓隊]墨墨的等式【同餘最短路】
- 【2024-ZR-C Day 6】資料結構(4):樹(重、長)鏈剖分、虛樹、dsu on tree資料結構
- P2757 [國家集訓隊] 等差子序列 與 CF452F Permutation
- C112 莫隊演算法 P1494 [國家集訓隊] 小 Z 的襪子演算法
- 樹剖(不太會)