BZOJ3589: 动态树
2016-03-22 21:32
309 查看
树链剖分。。
沃日打错树剖+路径并
感觉要滚粗啊
沃日打错树剖+路径并
感觉要滚粗啊
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> using namespace std; #define ll long long const ll Mod=1ll<<31; char c; inline void read(ll &a) { a=0;do c=getchar();while(c<'0'||c>'9'); while(c<='9'&&c>='0')a=(a<<3)+(a<<1)+c-'0',c=getchar(); } struct Chain { Chain *next; ll u; }*Head[300001]; #define ll long long ll Dep[300001]; namespace LC { ll Len[600001]; ll ST[1000001][20]; ll In[600001]; ll Block[600001]; ll tot; inline ll L(ll x,ll y){return Dep[x]<Dep[y]?x:y;} inline ll LCA(ll a,ll b) { if(!(a^b))return a; ll x=In[a],y=In[b]; if(x>y)swap(x,y); ll Len=y-x+1,Bl=Block[Len]; return L(ST[x][Bl],ST[y-(1<<Bl)+1][Bl]); } ll Dis(ll u,ll v){return Len[u]+Len[v]-2*Len[LCA(u,v)];} inline void Bg() { Len[0]=1ll<<29; Dep[0]=1ll<<29; ll base; for(ll i=1,base=1;i<=19;i++,base<<=1) for(ll j=1;j<=tot;j++) ST[j][i]=L(ST[j][i-1],ST[j+base][i-1]); ll con=0; for(ll i=1;i<=tot;i++) if(i^(i&-i))Block[i]=con-1; else Block[i]=con++; } void DFS(ll u,ll fa,ll dep) { Dep[u]=dep; ST[In[u]=++tot][0]=u; for(Chain*tp=Head[u];tp;tp=tp->next) if(tp->u^fa) { DFS(tp->u,u,dep+1); ST[++tot][0]=u; } if(u^fa)return ; Bg(); } } ll t; namespace Seg { struct N { ll l,r; ll sum,flag; }T[600001]; inline void Build(ll place,ll l,ll r) { ll Mid=l+r>>1,lc=place<<1,rc=lc|1; T[place].l=l,T[place].r=r; if(l^r) Build(lc,l,Mid),Build(rc,Mid+1,r); } inline void AddFlag(ll place,ll Delta) { T[place].flag+=Delta,T[place].sum+=Delta*(T[place].r-T[place].l+1); T[place].flag%=Mod,T[place].sum%=Mod; } inline void pushdown(ll place) { ll lc=place<<1,rc=lc|1; T[lc].flag+=T[place].flag,T[rc].flag+=T[place].flag; T[lc].sum+=T[place].flag*(T[lc].r-T[lc].l+1), T[rc].sum+=T[place].flag*(T[rc].r-T[rc].l+1); T[lc].flag%=Mod;T[rc].flag%=Mod; T[lc].sum%=Mod;T[rc].sum%=Mod; T[place].flag=0; } void Add(ll place,ll l,ll r,ll Delta) { if(T[place].l>=l&&T[place].r<=r) { AddFlag(place,Delta);return;} // if(T[place].flag)pushdown(place); ll lc=place<<1,rc=lc|1,Mid=T[lc].r; if(Mid<r)Add(rc,l,r,Delta); if(Mid>=l)Add(lc,l,r,Delta); T[place].sum=(T[lc].sum+T[rc].sum+T[place].flag*(T[place].r-T[place].l+1))%Mod; } ll Query(ll place,ll l,ll r) { if(T[place].l>=l&&T[place].r<=r)return T[place].sum; // if(T[place].flag)pushdown(place); ll res=T[place].flag*(min(r,T[place].r)-max(l,T[place].l)+1),lc=place<<1,rc=lc|1,Mid=T[lc].r; if(l<=Mid)res+=Query(lc,l,r); if(r>Mid)res+=Query(rc,l,r); res%=Mod; return res; } } struct Path{ll f,s;}; Path operator &(Path a,Path b) { Path res; res.f=LC::LCA(a.f,b.f); if(res.f==b.f)res.f=a.f; else if(res.f==a.f)res.f=b.f; else return (Path){-1,-1}; res.s=LC::LCA(a.s,b.s); if(Dep[res.f]>Dep[res.s])return (Path){-1,-1}; return res; } ll K; Path X[30001]; ll HeavySon[300001],Size[300001],F[300001]; void DFS(ll u,ll f) { Size[u]++; F[u]=f; for(Chain *tp=Head[u];tp;tp=tp->next) if(tp->u!=f) { DFS(tp->u,u); Size[u]+=Size[tp->u]; if(Size[tp->u]>Size[HeavySon[u]])HeavySon[u]=tp->u; } } ll tot,CBG[300001],CED[300001],CPL[300001],CND[300001]; void DFS2(ll u,ll f,ll BG) { CBG[u]=BG; CND[CPL[u]=++tot]=u; if(HeavySon[u]) DFS2(HeavySon[u],u,BG); for(Chain *tp=Head[u];tp;tp=tp->next) if(tp->u!=HeavySon[u]&&tp->u!=f) DFS2(tp->u,u,tot+1); CED[u]=tot; } ll Query(Path X) { ll res=0,u=X.f,v=X.s; while(CBG[v]!=CBG[u]) { res+=Seg::Query(1,CBG[v],CPL[v]); v=F[CND[CBG[v]]]; } res+=Seg::Query(1,CPL[u],CPL[v]); return res; } ll Add(ll u,ll Delta) { Seg::Add(1,CPL[u],CED[u],Delta); } ll Div(ll x,Path Tp) { if(x==K+1)return 0; if(Tp.f==4&&Tp.s==4) x++,x--; if(Tp.f==-1)return 0; ll res=Query(Tp); for(ll i=x+1;i<=K;i++) res-=Div(i,Tp&X[i]),res%=Mod; return res%Mod; } inline void ADD(ll a,ll b) { Chain *tp=new Chain; tp->u=b,tp->next=Head[a],Head[a]=tp; } ll n,Q ; int main() { read(n); ll i,j,k,l; for(i=1;i<n;i++) { read(j),read(k),ADD(j,k),ADD(k,j); } LC::DFS(1,1,1); DFS(1,1); DFS2(1,1,1); Seg::Build(1,1,tot); read(Q); while(Q--) { ll op; read(op); if(op) { read(K); ll ans=0,j,k; for(i=1;i<=K;i++) { read(j),read(k); X[i].f=Dep[j]<Dep[k]?j:k; X[i].s=j+k-X[i].f; } for(i=1;i<=K;i++) ans+=Div(i,X[i]); printf("%lld\n",(ans%Mod+Mod)%Mod); } else read(j),read(k),Add(j,k); } // printf("%d\n",t); return 0; }
相关文章推荐
- leetcode——290——Word Pattern
- B - Biorhythms——(中国剩余定理)
- FOJ FZU 2197 最小花费【贪心】
- 典型递归问题--爬楼梯
- 表格组件列属性formatter和styler使用方法
- struts自定义类型转换器,局部和全局
- crm服务调用测试
- parseSdkContent failed Could not initialize class android.graphics
- OSI七层模型的每一层都有哪些协议
- Tomcat7 starts too late on Ubuntu 14.04 x64 [Digitalocean]
- mysql 转发自 WhyWin
- C++智能指针简单剖析
- [android] smartimageview&常见的开源代码
- JS中关于函数调用的问题
- 第三次
- 连续因子
- 希望到2016.9.22前能完成一篇angualr结构的详解。
- 图解Javascript上下文与作用域
- CM 人物分析
- [leetcode 216] Combination Sum III ------组合数的和(回溯法)