나무 사슬 분할 (2)
14136 단어 데이터 구조
tim//
size[]// size
son[]//
fa[]//
dep[]//
top[]// ( )
tid[]//
Rank[]//
나무 사슬 을 나 눌 때 먼저 우 리 는 모든 노드 의 size 를 확정 하여 무 거 운 아들 을 확정 한 다음 에 무 거 운 변 으로 연결 해 야 한다.그 후에 우 리 는 다시 무 거 운 가장 자 리 를 연결 하여 무 거 운 사슬 로 만 들 었 다.이 과정 은 양쪽 dfs 가 필요 합 니 다.
void dfs1(int rt,int f,int depth){//
fa[rt]=f;//
dep[rt]=depth;//
size[rt]=1;//size 1( )
for(int i=head[rt];~i;i=edge[i].next){//
int v=edge[i].to;
if(v!=f){//
dfs1(v,rt,depth+1);
size[rt]+=size[v];// size
if(son[rt]==-1||size[son[rt]]<size[v])// ||size
son[rt]=v;
}
}
}
void dfs2(int rt,int tp){//tp
top[rt]=tp;
tid[rt]=++tim;
Rank[tim]=rt;
if(son[rt]==-1)return;
dfs2(son[rt],tp);// ,
for(int i=head[rt];~i;i=edge[i].next){
int v=edge[i].to;
if(v!=fa[rt]&&v!=son[rt])
dfs2(v,v);
}
}
tid & & Rank - 개인 적 으로 가장 이해 하기 어 려 운 나무 사슬 의 일부 나무 사슬 의 분할 은 시간 에 따라 전체 나 무 를 만 드 는 것 이 라 고 생각 합 니 다. 즉, 우리 가 노드 가 현재 체인 에 있 는 위 치 를 찾 으 려 고 할 때 tid 배열 은 중요 한 역할 을 합 니 다. tid [x] = tim 이 고 tim 이 대응 하 는 것 은 현재 체인 의 위치 이기 때 문 입 니 다.Rank 배열 은 현재 시각 에 대응 하 는 노드 입 니 다.그래서: x = Rank [tid [x]];이 를 이해 한 후에 우 리 는 tid 로 특정한 노드 에 대응 하 는 전체 체인 의 위 치 를 찾 을 수 있 고 Rank 으로 특정한 위치 에 대응 하 는 나무의 어느 노드 를 찾 을 수 있다. 그러면 전체 나 무 는 철저하게 체인 으로 전환 할 수 있다.그러나 어떤 것들 은 나무 사슬 의 분할 에 있어 서 당연 하 다 고 생각 할 수 없다. 예 를 들 어 LCA 라 는 것 이 있다. 처음에 나 는 나무의 두 가지 경로 의 소유권 치 를 바 꾸 는 것 이 순진 하 다 고 생각 했다. 그러면 이렇게 할 수 있다. 그들의 LCA 를 찾 아 한 경 로 를 두 개의 체인 으로 나 누 어 바 꾸 고 선분 나무 로 유지 할 수 있다.지금 생각해 보면........................................................................................그리고 LCA...............................................................................그 러 니까...(적어도 이 문 제 는 자신 을 함정 에 빠 뜨리 는 것 이다)
경로 구간 조작 시 dep [] 로 기괴 한 조작 을 하 세 요!
구간 수정 사고: x, y 간 의 경 로 를 구간 수정 합 니 다.
void chage(){
while(x,y ){
dep[top[x]]<dep[top[y]]?swap(x,y):1;
x---top[x] ;
x=fa[top[x]];
}
x---y 。
}
이 문제 의 코드 를 보 낼 때 가 되 었 습 니 다..........................................................................
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define N 50005
#define lc rt<<1,l,mid
#define rc rt<<1|1,mid+1,r
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
int n,m,p,cnt=0,tim=0;
int son[N],dep[N],Rank[N],size[N],tid[N],fa[N],head[N<<1],w[N],top[N],sum[N<<2],lazy[N<<2];
struct Edge{
int next,to;
}edge[N<<1];
void save(int u,int v){
edge[cnt].next=head[u];
edge[cnt].to=v;
head[u]=cnt++;
}
void dfs1(int rt,int f,int depth){
fa[rt]=f;
dep[rt]=depth;
size[rt]=1;
for(int i=head[rt];~i;i=edge[i].next){
int v=edge[i].to;
if(v!=f){
dfs1(v,rt,depth+1);
size[rt]+=size[v];
if(son[rt]==-1||size[son[rt]]<size[v])
son[rt]=v;
}
}
}
void dfs2(int rt,int tp){
top[rt]=tp;
tid[rt]=++tim;
Rank[tim]=rt;
if(son[rt]==-1)return;
dfs2(son[rt],tp);
for(int i=head[rt];~i;i=edge[i].next){
int v=edge[i].to;
if(v!=son[rt]&&v!=fa[rt])
dfs2(v,v);
}
}
//
void build(int rt,int l,int r){
lazy[rt]=0;
if(l==r){
sum[rt]=w[Rank[l]];
return;
}
int mid=(l+r)>>1;
build(lc);
build(rc);
}
void pushdown(int rt){
if(lazy[rt]){
lazy[rt<<1]+=lazy[rt];
lazy[rt<<1|1]+=lazy[rt];
sum[rt<<1]+=lazy[rt];
sum[rt<<1|1]+=lazy[rt];
lazy[rt]=0;
}
}
void modify(int rt,int l,int r,int lm,int rm,int modi){
if(l>rm||r<lm)return;
if(l>=lm&&r<=rm){
lazy[rt]+=modi;
sum[rt]+=modi*(r-l+1);
return;
}
int mid=(l+r)>>1;
pushdown(rt);
if(mid>=lm)modify(lc,lm,rm,modi);
if(mid<rm)modify(rc,lm,rm,modi);
}
void Change(int x,int y,int val) //
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]]) swap(x,y);
modify(1,1,n,tid[top[x]],tid[x],val);
x=fa[top[x]];
}
if(dep[x]>dep[y]) swap(x,y);
modify(1,1,n,tid[x],tid[y],val);
}
int query(int rt,int l,int r,int q){
if(l==r)return sum[rt];
int mid=(l+r)>>1;
pushdown(rt);
int ans=0;
if(mid>=q)ans=query(lc,q);
if(mid<q)ans=query(rc,q);
return ans;
}
int main (){
while(~scanf("%d%d%d",&n,&m,&p)){
memset(head,-1,sizeof(head));
memset(edge,0,sizeof(edge));
cnt=tim=0;
memset(son,-1,sizeof(son));
for(int i=1;i<=n;i++)
scanf("%d",&w[i]);
for(int i=1;i<=m;i++){
int u,v;
scanf("%d%d",&u,&v);
save(u,v);save(v,u);
}
dfs1(1,0,0);
dfs2(1,1);
build(1,1,n);
for(int i=1;i<=p;i++){
char c[5];
scanf("%s",c);
if(c[0]=='Q'){
int q;
scanf("%d",&q);
printf("%d
",query(1,1,n,tid[q]));
}
else {
int c1,c2,cg;
scanf("%d%d%d",&c1,&c2,&cg);
if(c[0]=='D')
Change(c1,c2,-cg);
else
Change(c1,c2,cg);
}
}
}
return 0;
}
이로써 간단 한 나무 사슬 분할 모형 문제 분석 이 완료 되 었 습 니 다!'간단 하 다' 는 단 어 는 '모형 문제' 를 수식 하 는 것 이지 나무 사슬 로 나 누 는 것 이 아 닙 니 다. (엄숙 한 얼굴)
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
정수 반전Udemy 에서 공부 한 것을 중얼거린다 Chapter3【Integer Reversal】 (예) 문자열로 숫자를 반전 (toString, split, reverse, join) 인수의 수치 (n)가 0보다 위 또는 ...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.