bzoj3531: [Sdoi2014]旅行(樹鏈剖分+線段樹)
題目傳送門
。
解法:
據說叫動態開點。
需要用的點才建線段樹。
那麼最多隻有二十萬種不同的資訊。。
跟主席樹一樣嘛。
YY就好了
程式碼實現:
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
using namespace std;
struct node {int x,y,next;}a[210000];int len,last[110000];
void ins(int x,int y) {len++;a[len].x=x;a[len].y=y;a[len].next=last[x];last[x]=len;}
int n,fa[110000],tot[110000],dep[110000],son[110000];
void pre_tree_node(int x) {
tot[x]=1;son[x]=0;
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(y!=fa[x]) {
fa[y]=x;dep[y]=dep[x]+1;pre_tree_node(y);
tot[x]+=tot[y];if(tot[son[x]]<tot[y])son[x]=y;
}
}
}
int z,ys[110000],top[110000];
void pre_tree_edge(int x,int tp) {
ys[x]=++z;top[x]=tp;
if(son[x]!=0)pre_tree_edge(son[x],tp);
for(int k=last[x];k;k=a[k].next) {
int y=a[k].y;
if(y!=fa[x]&&y!=son[x]) pre_tree_edge(y,y);
}
}
struct trnode {int lc,rc,c,mx;}tr[5100000];int trlen,rt[210000];
void change(int &now,int l,int r,int x,int k) {
if(now==0)now=++trlen;
if(l==r){tr[now].c=tr[now].mx=k;return ;}
int mid=(l+r)/2;
if(x<=mid)change(tr[now].lc,l,mid,x,k);
else change(tr[now].rc,mid+1,r,x,k);
tr[now].c=tr[tr[now].lc].c+tr[tr[now].rc].c;
tr[now].mx=max(tr[tr[now].lc].mx,tr[tr[now].rc].mx);
}
int find_sum(int now,int l,int r,int x,int y) {
if(now==0)return 0;if(l==x&&r==y)return tr[now].c;
int mid=(l+r)/2;
if(y<=mid)return find_sum(tr[now].lc,l,mid,x,y);
else if(x>mid)return find_sum(tr[now].rc,mid+1,r,x,y);
else return find_sum(tr[now].lc,l,mid,x,mid)+find_sum(tr[now].rc,mid+1,r,mid+1,y);
}
int find_max(int now,int l,int r,int x,int y) {
if(now==0)return 0;if(l==x&&r==y)return tr[now].mx;
int mid=(l+r)/2;
if(y<=mid)return find_max(tr[now].lc,l,mid,x,y);
else if(x>mid)return find_max(tr[now].rc,mid+1,r,x,y);
else return max(find_max(tr[now].lc,l,mid,x,mid),find_max(tr[now].rc,mid+1,r,mid+1,y));
}
int solve_sum(int x,int y,int c) {
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans+=find_sum(rt[c],1,n,ys[ty],ys[y]);y=fa[ty];ty=top[y];
}if(dep[x]>dep[y]) swap(x,y);
ans+=find_sum(rt[c],1,n,ys[x],ys[y]);return ans;
}
int solve_max(int x,int y,int c) {
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty) {
if(dep[tx]>dep[ty]) {swap(tx,ty);swap(x,y);}
ans=max(ans,find_max(rt[c],1,n,ys[ty],ys[y]));y=fa[ty];ty=top[y];
}if(dep[x]>dep[y]) swap(x,y);
return max(ans,find_max(rt[c],1,n,ys[x],ys[y]));
}
char s[5];
int jh[110000],pj[110000];
int main() {
int m;scanf("%d%d",&n,&m);len=0;memset(last,0,sizeof(last));
for(int i=1;i<=n;i++) scanf("%d%d",&pj[i],&jh[i]);
for(int i=1;i<n;i++) {int x,y;scanf("%d%d",&x,&y);ins(x,y);ins(y,x);}
dep[1]=0;fa[1]=0;pre_tree_node(1);z=0;pre_tree_edge(1,1);trlen=0;
for(int i=1;i<=n;i++) change(rt[jh[i]],1,n,ys[i],pj[i]);
while(m--) {
int x,y;scanf("%s%d%d",s+1,&x,&y);
if(s[1]=='C') {
if(s[2]=='C') {
change(rt[jh[x]],1,n,ys[x],0);jh[x]=y;
change(rt[jh[x]],1,n,ys[x],pj[x]);
}else {pj[x]=y;change(rt[jh[x]],1,n,ys[x],pj[x]);}
}else {
if(s[2]=='S') printf("%d\n",solve_sum(x,y,jh[x]));
else printf("%d\n",solve_max(x,y,jh[x]));
}
}
return 0;
}
相關文章
- TZOJ 8472 : Tree (重鏈剖分+線段樹) POJ 3237
- 樹鏈剖分
- [OI] 樹鏈剖分
- 2024.3.14 樹鏈剖分
- 淺談樹鏈剖分
- 樹鏈剖分總結
- Something about 樹鏈剖分
- 【筆記/模板】樹鏈剖分筆記
- #8. 「模板」樹鏈剖分
- [LOJ139]-樹鏈剖分
- 迴文樹線上剖分???
- 「學習筆記」樹鏈剖分筆記
- 樹鏈剖分學習筆記筆記
- 對樹鏈剖分的愛 題解
- P8025 【樹鏈剖分求祖先】
- bzoj4551: [Tjoi2016&Heoi2016]樹(樹鏈剖分)
- 樹鏈剖分解析
- 樹鏈剖分模板+入門題 SPOJ - QTREEQT
- 樹剖 dsu on tree 長鏈
- bzoj3626: [LNOI2014]LCA(離線處理+樹鏈剖分)
- 一起來學習樹鏈剖分吧!
- 線段樹
- 線~段~樹
- 線段樹差分及其應用
- 熟練剖分(tree) 樹形DP
- 01 線段樹
- 線段樹--RMQMQ
- 【模版】線段樹
- 線段樹模板
- 線段樹 hate it
- BF的資料結構題單-提高組——樹鏈剖分資料結構
- P1505 [國家集訓隊]旅遊 (樹鏈剖分)
- 樹剖(不太會)
- 資料結構之樹( 線段樹,字典樹)資料結構
- 【2024-ZR-C Day 6】資料結構(4):樹(重、長)鏈剖分、虛樹、dsu on tree資料結構
- 李超線段樹
- 線段樹進階
- 權值線段樹