1. 程式人生 > >BZOJ4448 SCOI2015情報傳遞(離線+樹鏈剖分+樹狀數組)

BZOJ4448 SCOI2015情報傳遞(離線+樹鏈剖分+樹狀數組)

fin tree amp tdi 開始 情報 路徑 stream from

  即滋磁單點修改,詢問路徑上小於某數的值有多少個。暴力樹剖套個主席樹即可,然而不太優美。

  開始覺得可以cdq,然而就變成log^3了。冷靜一下感覺簡直是個弱智,修改本身就是單調的,只要對詢問離線即可。樹剖+BIT即可維護。

#include<iostream> 
#include<cstdio>
#include<cmath>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
int read()
{
    int
x=0,f=1;char c=getchar(); while (c<0||c>9) {if (c==-) f=-1;c=getchar();} while (c>=0&&c<=9) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } #define N 200010 int n,m,root,fa[N],deep[N],p[N],t=0,cnt,cntu,cntq; int top[N],id[N],son[N],size[N],tree[N]; struct
data{int to,nxt; }edge[N]; struct data2{int x,i; }u[N]; struct data3{int x,y,z,i,ans; }q[N]; void addedge(int x,int y){t++;edge[t].to=y,edge[t].nxt=p[x],p[x]=t;} bool cmp(const data3&a,const data3&b) { return a.z<b.z; } bool cmp1(const data3&a,const data3&b) { return a.i<b.i; }
void dfs1(int k) { size[k]=1; for (int i=p[k];i;i=edge[i].nxt) { deep[edge[i].to]=deep[k]+1; dfs1(edge[i].to); size[k]+=size[edge[i].to]; if (size[edge[i].to]>size[son[k]]) son[k]=edge[i].to; } } void dfs2(int k,int from) { top[k]=from;id[k]=++cnt; if (son[k]) dfs2(son[k],from); for (int i=p[k];i;i=edge[i].nxt) if (edge[i].to!=son[k]) dfs2(edge[i].to,edge[i].to); } void mbit(int k){while (k<=n) tree[k]++,k+=k&-k;} int qbit(int k){int s=0;while (k) s+=tree[k],k-=k&-k;return s;} int lca(int x,int y) { while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); x=fa[top[x]]; } return deep[x]<deep[y]?x:y; } int query(int x,int y) { int s=0; while (top[x]!=top[y]) { if (deep[top[x]]<deep[top[y]]) swap(x,y); s+=qbit(id[x])-qbit(id[top[x]]-1); x=fa[top[x]]; } if (deep[x]<deep[y]) swap(x,y); s+=qbit(id[x])-qbit(id[y]-1); return s; } int main() { #ifndef ONLINE_JUDGE freopen("bzoj4448.in","r",stdin); freopen("bzoj4448.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(); for (int i=1;i<=n;i++) { fa[i]=read(); if (fa[i]==0) root=i,fa[i]=i; else addedge(fa[i],i); } dfs1(root); dfs2(root,root); m=read(); for (int i=1;i<=m;i++) { int op=read(); if (op==1) cntq++,q[cntq].x=read(),q[cntq].y=read(),q[cntq].z=i-read()-1,q[cntq].i=i; else cntu++,u[cntu].x=read(),u[cntu].i=i; } sort(q+1,q+cntq+1,cmp); int x=0; for (int i=1;i<=cntq;i++) if (q[i].z>0) { while (x<cntu&&u[x+1].i<=q[i].z) mbit(id[u[++x].x]); q[i].ans=query(q[i].x,q[i].y); } sort(q+1,q+cntq+1,cmp1); for (int i=1;i<=cntq;i++) printf("%d %d\n",deep[q[i].x]+deep[q[i].y]-(deep[lca(q[i].x,q[i].y)]<<1)+1,q[i].ans); return 0; }

BZOJ4448 SCOI2015情報傳遞(離線+樹鏈剖分+樹狀數組)