[학습노트] MysC_K의 독립집 좋은 문제 - 동적 dp - 나무 해부 - 전역 균형 두 갈래 나무 - 학습 노트
63814 단어 학습 노트동적 dp트리 체인 분할과 dfs 순서
하나의 로그로 머리를 쓰다.아니면 두 개의 로그와 비슷한 방법으로 먼저 체인을 나누어 치료한 다음에 현재 우리는 라인 트리로 모든 무거운 체인을 유지하지 않는다.우리는 무거운 사슬의 각 점에 대해 가벼운 나무의size의 합을 구하고 +1을 구한 다음에 현재 사슬의 중심을 선택하여 나무를 세운다.이렇게 하면 각 점은 체인의 구간에 대응한다.이렇게 하는 장점은 매번 가벼운 테두리(두 개의 무거운 사슬을 연결하는 나무의 테두리로 볼 수 있음)를 지나갈 때마다size는 최소한 반을 줄일 수 있다는 것이다.건설된 나무의 한 변을 지나면 점이 중체인 구간에 대응하는 연결 블록의 크기도 적어도 반으로 줄어든다.따라서 매번 위로 뛰는 총 복잡도는 O(logn)이다.
#include
#define rep(i,a,b) for(int i=a;i<=b;i++)
#define gc getchar()
#define debug(x) cerr<
#define sp <
#define ln <
using namespace std;
inline int inn()
{
int x,ch,sgn=1;while(((ch=gc)<'0'||ch>'9')&&ch!='-');
if(ch=='-') sgn=-1,x=0;else x=ch^'0';
while((ch=gc)>='0'&&ch<='9') x=(x<<1)+(x<<3)+(ch^'0');
return x*sgn;
}
#define Max(a,b,c) max(max(a,b),c)
const int N=100010;
struct edges{
int to,pre;
}e[N<<1];int h[N],etop,a[N],f[N],g[N],fq[N],gq[N],in[N],out[N],tms[N],dfc,fa[N],lst[N];
int top[N],sz[N],son[N],szq[N],bot[N];
inline int add_edge(int u,int v) { return e[++etop].to=v,e[etop].pre=h[u],h[u]=etop; }
namespace TREE_SPACE{
int ncnt,fa[N],pre[N],suf[N],pos[N],lc[N],rc[N],id[N];
struct node{
int w00,w01,w10,w11;
node() { w00=w01=w10=w11=0; }
node(int f,int g) { w00=g,w11=f,w01=w10=0; }
inline node operator+(const node &n)const
{
static node t;
t.w00=Max(w00+n.w00,w00+n.w10,w01+n.w00);
t.w01=Max(w00+n.w01,w00+n.w11,w01+n.w01);
t.w10=Max(w10+n.w00,w10+n.w10,w11+n.w00);
t.w11=Max(w10+n.w01,w10+n.w11,w11+n.w01);
return t;
}
inline node operator+=(const node &n) { return (*this)=(*this)+n; }
inline int f()const { return max(w10,w11); }
inline int g()const { return max(w00,w01); }
inline int ans()const { return max(f(),g()); }
inline int show()const { debug(w00)sp,debug(w01)sp,debug(w10)sp,debug(w11)ln;return 0; }
}val[N],s[N];
inline int new_node(int f,int g)
{
int x=++ncnt;fa[x]=lc[x]=rc[x]=0;
val[x]=s[x]=node(f,g);return x;
}
inline int push_up(int x)
{
s[x]=val[x];
if(lc[x]) s[x]=s[lc[x]]+s[x];
if(rc[x]) s[x]=s[x]+s[rc[x]];
return 0;
}
inline int Build(int *f,int *g,int *sz,int l,int r)
{
int p=l;if(l>r) return 0;
pre[l-1]=suf[r+1]=0;rep(i,l,r) pre[i]=pre[i-1]+sz[tms[i]];
for(int i=r;i>=l;i--) suf[i]=suf[i+1]+sz[tms[i]];
rep(i,l+1,r) if(max(pre[i-1],suf[i+1])<max(pre[p-1],suf[p+1])) p=i;
int x=new_node(f[tms[p]],g[tms[p]]);pos[p]=x,id[x]=p;
lc[x]=Build(f,g,sz,l,p-1),rc[x]=Build(f,g,sz,p+1,r);
if(lc[x]) fa[lc[x]]=x;if(rc[x]) fa[rc[x]]=x;return push_up(x),x;
}
node Query(int x,int p)
{
if(id[x]<p) return Query(rc[x],p);
node ans=val[x];if(rc[x]) ans+=s[rc[x]];
if(p<id[x]) ans=Query(lc[x],p)+ans;return ans;
}
struct My_Tree{
int rt;
inline int build(int *f,int *g,int *sz,int l,int r) { return rt=Build(f,g,sz,l,r); }
inline int query(int p) { return Query(rt,p).ans(); }
inline int update(int p,int f,int g) { int x=pos[p];val[x]=node(f,g);while(x) push_up(x),x=fa[x];return 0; }
inline int f() { return s[rt].f(); }
inline int g() { return s[rt].g(); }
inline int ans() { return s[rt].ans(); }
}tr[N];
}
using TREE_SPACE::tr;
int fir_dfs(int x,int fa=0)
{
for(int i=h[x],y;i;i=e[i].pre)
if((y=e[i].to)^fa)
{
sz[x]+=fir_dfs(y,x);
if(sz[y]>sz[son[x]]) son[x]=y;
}
return ++sz[x];
}
int sec_dfs(int x)
{
fq[x]=a[x],gq[x]=0,tms[in[x]=++dfc]=x,szq[x]=1;
if(son[x]) fa[son[x]]=x,top[son[x]]=top[x],sec_dfs(son[x]),bot[x]=bot[son[x]];else bot[x]=x;
for(int i=h[x],y;i;i=e[i].pre) if((y=e[i].to)!=fa[x]&&e[i].to!=son[x])
fa[y]=x,top[y]=y,sec_dfs(y),fq[x]+=g[y],gq[x]+=max(f[y],g[y]),szq[x]+=sz[y];
if(son[x]) f[x]=fq[x]+g[son[x]],g[x]=gq[x]+max(f[son[x]],g[son[x]]);
else f[x]=fq[x],g[x]=gq[x];return out[x]=dfc;
}
inline int upd(int x,int v)
{
int cnt=0;for(int y=top[x];fa[y];y=top[fa[y]]) lst[++cnt]=y;
for(int i=cnt,y,z;i;i--) y=lst[i],z=fa[y],
tr[top[z]].update(in[z],fq[z]-=tr[y].g(),gq[z]-=tr[y].ans());
tr[top[x]].update(in[x],fq[x]+=v,gq[x]);
for(int y=top[x],z=fa[y];z;z=fa[y=top[z]])
tr[top[z]].update(in[z],fq[z]+=tr[y].g(),gq[z]+=tr[y].ans());
return 0;
}
char ss[3000010],tt[20];int ssl,ttl;
inline int show(int x)
{
if(!x) ss[++ssl]='0';for(ttl=0;x;x/=10) tt[++ttl]=char(x%10+'0');
for(;ttl;ttl--) ss[++ssl]=tt[ttl];return ss[++ssl]='
';
}
int main()
{
int n=inn(),q=inn(),u,v,x;
rep(i,2,n) u=inn(),v=inn(),add_edge(u,v),add_edge(v,u);
rep(i,1,n) a[i]=inn();
fir_dfs(1),top[1]=1,sec_dfs(1);
rep(x,1,n) if(x==top[x]) tr[x].build(fq,gq,szq,in[x],in[bot[x]]);
while(q--)
if(inn()) x=inn(),upd(x,inn());
else x=inn(),printf("%d
",tr[top[x]].query(in[x]));
return fwrite(ss+1,sizeof(char),ssl,stdout),0;
}
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
axios 요청 차단, 응답 차단,router 내비게이션 수위axios 요청 차단: 요청 헤더에 token 등을 통일적으로 추가할 수 있습니다 axios 응답 차단: 로그인 판단 내비게이션 선행 수위beforeEach: 로그인 여부를 판단할 수 있지만, 응답으로 차단하는 것이...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.