嗯。。。企圖做ZJOI2011,結果一題都不會QAQ。生氣的寫樹剖來了~
這題暴力的樹剖是可以的,但我是在黃學長那找了這題,他好像有個非常妙的做法,現在差不多要去打ball了,之后再學習一下吧。
樹剖:
#include<cstdio> #include<cstring> #include<cstdlib> #include<cmath> #include<algorithm> #include<iostream> #include<string> #include<ctime> #include<queue> #include<map> #include<set> #include<vector> typedef long long LL; using namespace std; const int N=300010; struct edge{int to,nxt;}e[N<<1]; struct node{int l,r,lazy;}a[N<<2]; int n,b[N],head[N],cnt,pos[N],siz[N],bel[N],fa[N]; int read() {int d=0,f=1; char c=getchar(); while (c<'0'||c>'9') {if (c=='-') f=-1; c=getchar();} while (c>='0'&&c<='9') d=(d<<3)+(d<<1)+c-48,c=getchar(); return d*f;} void judge(){freopen(".in","r",stdin); freopen(".out","w",stdout);} void addedge(int x,int y) { e[++cnt]=(edge){y,head[x]}; head[x]=cnt; e[++cnt]=(edge){x,head[y]}; head[y]=cnt; } void dfs(int u) { siz[u]=1; for (int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if (v==fa[u]) continue; fa[v]=u; dfs(v); siz[u]+=siz[v]; } } void dfs2(int u,int Bel) { pos[u]=++cnt; bel[u]=Bel; int x=0; for (int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if (v==fa[u]) continue; if (siz[v]>siz[x]) x=v; } if (!x) return; dfs2(x,Bel); for (int i=head[u];i;i=e[i].nxt) { int v=e[i].to; if (v==fa[u]||v==x) continue; dfs2(v,v); } } void pushdown(int k) { if (!a[k].lazy) return; int k1=k<<1,k2=k1|1; a[k1].lazy+=a[k].lazy; a[k2].lazy+=a[k].lazy; a[k].lazy=0; } void build(int k,int l,int r) { a[k]=(node){l,r,0}; if (l==r) return; int mid=(l+r)>>1; build(k<<1,l,mid); build(k<<1|1,mid+1,r); } void update(int k,int l,int r,int v) { if (l<=a[k].l&&a[k].r<=r) {a[k].lazy+=v; return;} pushdown(k); int mid=(a[k].l+a[k].r)>>1; if (r<=mid) update(k<<1,l,r,v); else if (l>mid) update(k<<1|1,l,r,v); else update(k<<1,l,mid,v),update(k<<1|1,mid+1,r,v); } int ask(int k,int x) { if (a[k].l==a[k].r) return a[k].lazy; pushdown(k); int mid=(a[k].l+a[k].r)>>1; if (x<=mid) return ask(k<<1,x); else return ask(k<<1|1,x); } int main() { //judge(); n=read(); for (int i=1;i<=n;i++) b[i]=read(); for (int i=1;i<n;i++) addedge(read(),read()); dfs(1); cnt=0; dfs2(1,1); build(1,1,n); int x=b[1]; for (int i=2;i<=n;i++) { int y=b[i]; while (bel[x]!=bel[y]) { if (pos[x]<pos[y]) swap(x,y); update(1,pos[bel[x]],pos[x],1); x=fa[bel[x]]; } if (pos[x]>pos[y]) swap(x,y); update(1,pos[x],pos[y],1); x=b[i]; update(1,pos[x],pos[x],-1); } for (int i=1;i<=n;i++) printf("%d\n",ask(1,pos[i])); return 0; }
未完待續...
摘自黃學長:http://hzwer.com/4522.html
其實是可以直接上樹鏈剖分的
但是我們發現這道題只要實現每次將u-v路徑的點權+1
只要在u和v上打個+1標記,lca(u,v)和lca(u,v)->fa打-1標記,最后dp上傳標記即可
本質是個差分。。。
代碼就不寫了~\(≧▽≦)/~啦啦啦
完結~
本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系我们删除。