【Learning】动态树分治题目汇总
2017-12-10 10:14
274 查看
这里主要是我的动态点分治的练习记录。
动态点分治就是可以修改信息的点分治。在机房里面观战学长互怼对方“XXX为什么那么假?” 以及大神zjt学长:“点分治是什么?不会啊” 23333333。
T1 bzoj1095 动态点分治+堆
常数上天了!
T2 bzoj3730 动态树分治+线段树乱搞
RE得要死==
T3 bzoj4372 动态树分治+线段树
RMQ求lca居然打错==
T4 bzoj4012
在二分那里卡了好久,一气之下手打二分。(silly STL!) 一对比,树剖+主席树真的是太优越了!
动态点分治就是可以修改信息的点分治。在机房里面观战学长互怼对方“XXX为什么那么假?” 以及大神zjt学长:“点分治是什么?不会啊” 23333333。
T1 bzoj1095 动态点分治+堆
常数上天了!
#include<cstdio> #include<queue> #include<algorithm> using namespace std; const int N=100005; int n,m,u,v,cnt,idx,head ,to[N*2],nxt[N*2],dep ,dfn ,siz ,Log2[N*2],pos[N*2],f[N*2][20]; int rt,mi,size,fa ; bool vis ,ck ; char *p,s[10],ch[20000005]; inline int rd(){ register int ret=0; while(*p<'0'||*p>'9'){ p++; } while(*p>='0'&&*p<='9'){ ret=ret*10+*p-'0'; p++; } return ret; } void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int pre,int u){ dfn[u]=++idx; pos[idx]=u; siz[u]=1; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre){ dep[v]=dep[u]+1; dfs(u,v); pos[++idx]=u; siz[u]+=siz[v]; } } } void st(){ for(int i=1;i<=idx;i++){ f[i][0]=pos[i]; } for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=idx;i++){ if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){ f[i][j]=f[i][j-1]; }else{ f[i][j]=f[i+(1<<(j-1))][j-1]; } } } } int lca(int u,int v){ if(dfn[v]<dfn[u]){ swap(u,v); } int k=Log2[dfn[v]-dfn[u]]; if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){ return f[dfn[u]][k]; }else{ return f[dfn[v]-(1<<k)+1][k]; } } int dis(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } void dfsroot(int pre,int u){ siz[u]=1; int v,mx=0; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre&&!vis[v]){ dfsroot(u,v); siz[u]+=siz[v]; mx=max(mx,siz[v]); } } mx=max(mx,size-siz[u]); if(mx<mi){ rt=u; mi=mx; } } void dfstree(int pre,int u){ vis[u]=true; fa[u]=pre; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]){ mi=size=siz[v]; dfsroot(u,v); dfstree(u,rt); } } } struct heap{ priority_queue<int> A,B; void push(int x){ A.push(x); } void remove(int x){ B.push(x); } void pop(){ while(B.size()&&A.top()==B.top()){ A.pop(); B.pop(); } if(A.size()){ A.pop(); } } int top(){ while(B.size()&&A.top()==B.top()){ A.pop(); B.pop(); } return A.size()?A.top():0; } int size(){ return A.size()-B.size(); } int sectop(){ if(size()<2){ return 0; } int x=top(); pop(); int y=top(); push(x); return y; } }A,B ,C ; void insert(int x){ if(B[x].size()>=2){ A.push(B[x].top()+B[x].sectop()); } } void remove(int x){ if(B[x].size()>=2){ A.remove(B[x].top()+B[x].sectop()); } } void off(int u){ remove(u); B[u].push(0); insert(u); for(int i=u;fa[i];i=fa[i]){ remove(fa[i]); if(C[i].size()){ B[fa[i]].remove(C[i].top()); } C[i].push(dis(fa[i],u)); if(C[i].size()){ B[fa[i]].push(C[i].top()); } insert(fa[i]); } } void on(int u){ remove(u); B[u].remove(0); insert(u); for(int i=u;fa[i];i=fa[i]){ remove(fa[i]); if(C[i].size()){ B[fa[i]].remove(C[i].top()); } C[i].remove(dis(fa[i],u)); if(C[i].size()){ B[fa[i]].push(C[i].top()); } insert(fa[i]); } } int main(){ fread(ch,20000000,1,stdin); p=ch; for(int i=2;i<=200000;i++){ Log2[i]=Log2[i/2]+1; } n=rd(); for(int i=1;i<n;i++){ u=rd(),v=rd(); adde(u,v); adde(v,u); } dfs(0,1); st(); mi=size=siz[1]; dfsroot(0,1); dfstree(0,rt); for(int i=1;i<=n;i++){ for(int j=i;fa[j];j=fa[j]){ C[j].push(dis(fa[j],i)); } } for(int i=1;i<=n;i++){ if(fa[i]){ B[fa[i]].push(C[i].top()); } } for(int i=1;i<=n;i++){ B[i].push(0); ck[i]=false; insert(i); } cnt=n; m=rd(); for(int i=1;i<=m;i++){ s[0]=*p; p++; while(s[0]!='G'&&s[0]!='C'){ s[0]=*p; p++; } if(s[0]=='G'){ if(cnt<=1){ printf("%d\n",cnt-1); }else{ printf("%d\n",A.top()); } }else{ u=rd(); if(!ck[u]){ if(i==3){ u++; u--; } on(u); cnt--; ck[u]=true; }else{ off(u); cnt++; ck[u]=false; } } } return 0; }
T2 bzoj3730 动态树分治+线段树乱搞
RE得要死==
#include<cstdio> #include<algorithm> using namespace std; const int N=200005; int n,m,op,u,v,cnt,idx,tot,ans,Log2[N*2],a ,head ,to[N*2],nxt[N*2],dfn ,dep ,siz ,pos[N*2],f[N*2][25]; int rt,mi,size,fa ,root [2],sumv[N*50],ch[N*50][2],dd ; bool vis ; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; 13879 head[u]=cnt; } void dfs(int pre,int u){ dfn[u]=++idx; pos[idx]=u; siz[u]=1; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre){ dep[v]=dep[u]+1; dfs(u,v); siz[u]+=siz[v]; pos[++idx]=u; } } } void st(){ for(int i=1;i<=idx;i++){ f[i][0]=pos[i]; } for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=idx;i++){ if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){ f[i][j]=f[i][j-1]; }else{ f[i][j]=f[i+(1<<(j-1))][j-1]; } } } } int lca(int u,int v){ if(dfn[u]>dfn[v]){ swap(u,v); } int k=Log2[dfn[v]-dfn[u]]; if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){ return f[dfn[u]][k]; }else{ return f[dfn[v]-(1<<k)+1][k]; } } int dis(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } void upd(int &o,int l,int r,int k,int v){ if(!o){ o=++tot; } sumv[o]+=v; if(l==r){ return; } int mid=(l+r)/2; if(k<=mid){ upd(ch[o][0],l,mid,k,v); }else{ upd(ch[o][1],mid+1,r,k,v); } } int qry(int o,int l,int r,int L,int R){ if(!o){ return 0; } if(L<=l&&R>=r){ return sumv[o]; } int mid=(l+r)/2,ans=0; if(L<=mid){ ans+=qry(ch[o][0],l,mid,L,R); }if(R>mid){ ans+=qry(ch[o][1],mid+1,r,L,R); } return ans; } void dfsroot(int pre,int u){ siz[u]=1; int v,mx=0; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]&&v!=pre){ dfsroot(u,v); siz[u]+=siz[v]; mx=max(mx,siz[v]); } } mx=max(mx,size-siz[u]); if(mx<mi){ rt=u; mi=mx; } } void init(int rt,int md,int pre,int u){ upd(root[rt][md],0,n,dd[u],a[u]); int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]&&v!=pre){ dd[v]=dd[u]+1; init(rt,md,u,v); } } } void dfstree(int u){ vis[u]=true; int v; dd[u]=0; init(u,0,0,u); for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]){ mi=size=siz[v]; dd[v]=1; dfsroot(u,v); init(rt,1,u,v); fa[rt]=u; dfstree(rt); } } } int query(int u,int d){ int ans=qry(root[u][0],0,n,0,d),tmp; for(int i=u;fa[i];i=fa[i]){ tmp=dis(fa[i],u); ans+=qry(root[fa[i]][0],0,n,0,d-tmp)-qry(root[i][1],0,n,0,d-tmp); } return ans; } void update(int u,int k){ int tmp; upd(root[u][0],0,n,0,k-a[u]); for(int i=u;fa[i];i=fa[i]){ tmp=dis(fa[i],u); upd(root[fa[i]][0],0,n,tmp,k-a[u]); upd(root[i][1],0,n,tmp,k-a[u]); } a[u]=k; } int main(){ for(int i=2;i<=200000;i++){ Log2[i]=Log2[i/2]+1; } scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } dfs(0,1); st(); size=mi=siz[1]; dfsroot(0,1); dfstree(rt); for(int i=1;i<=m;i++){ scanf("%d%d%d",&op,&u,&v); u^=ans; v^=ans; if(op==0){ printf("%d\n",ans=query(u,v)); }else{ update(u,v); } } return 0; }
T3 bzoj4372 动态树分治+线段树
RMQ求lca居然打错==
#include<cstdio> #include<algorithm> using namespace std; const int N=100005; int n,m,u,v,d,cnt,head ,to[N*2],nxt[N*2]; int idx,lg2[N*2],dfn ,dep ,siz ,pos[N*2],f[N*2][20]; int mi,size,rt,fa ; int tot,root [2],tag[20000005],ch[20000005][2]; bool vis ; char s[5]; void adde(int u,int v){ to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; } void dfs(int pre,int u){ dfn[u]=++idx; pos[idx]=u; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre){ dep[v]=dep[u]+1; dfs(u,v); pos[++idx]=u; } } } void st(){ for(int i=1;i<=idx;i++){ f[i][0]=pos[i]; } for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=idx;i++){ if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){ f[i][j]=f[i][j-1]; }else{ f[i][j]=f[i+(1<<(j-1))][j-1]; } } } } int lca(int u,int v){ if(dfn[u]>dfn[v]){ swap(u,v); } int k=lg2[dfn[v]-dfn[u]]; if(dep[f[dfn[u]][k]]<dep[f[dfn[v]-(1<<k)+1][k]]){ return f[dfn[u]][k]; }else{ return f[dfn[v]-(1<<k)+1][k]; } } void dfsroot(int pre,int u){ siz[u]=1; int v,mx=0; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre&&!vis[v]){ dfsroot(u,v); siz[u]+=siz[v]; mx=max(mx,siz[v]); } } mx=max(mx,size-siz[u]); if(mx<mi){ mi=mx; rt=u; } } int dis(int u,int v){ return dep[u]+dep[v]-2*dep[lca(u,v)]; } void build(int pre,int u){ vis[u]=true; fa[u]=pre; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]){ mi=size=siz[v]; dfsroot(u,v); build(u,rt); } } } void upd(int &o,int l,int r,int L,int R,int v){ if(!o){ o=++tot; } if(L==l&&R==r){ tag[o]+=v; return; } int mid=(l+r)/2; if(R<=mid){ upd(ch[o][0],l,mid,L,R,v); }else if(L>mid){ upd(ch[o][1],mid+1,r,L,R,v); }else{ upd(ch[o][0],l,mid,L,mid,v); upd(ch[o][1],mid+1,r,mid+1,R,v); } } int qry(int o,int l,int r,int k){ if(!o){ return 0; } if(l==r){ return tag[o]; } int mid=(l+r)/2; if(k<=mid){ return tag[o]+qry(ch[o][0],l,mid,k); }{ return tag[o]+qry(ch[o][1],mid+1,r,k); } } int query(int u){ int ret=qry(root[u][0],0,n,0),tmp; for(int i=u;fa[i];i=fa[i]){ tmp=dis(fa[i],u); ret+=qry(root[fa[i]][0],0,n,tmp)-qry(root[i][1],0,n,tmp); } return ret; } void update(int u,int d,int w){ upd(root[u][0],0,n,0,d,w); int tmp; for(int i=u;fa[i];i=fa[i]){ tmp=dis(fa[i],u); if(tmp>d){ continue; } upd(root[fa[i]][0],0,n,0,d-tmp,w); upd(root[i][1],0,n,0,d-tmp,w); } } int main(){ for(int i=2;i<=200000;i++){ lg2[i]=lg2[i/2]+1; } scanf("%d%d",&n,&m); for(int i=1;i<n;i++){ scanf("%d%d",&u,&v); adde(u,v); adde(v,u); } dfs(0,1); st(); mi=size=n; dfsroot(0,1); build(0,rt); for(int i=1;i<=m;i++){ scanf("%s%d",s,&u); if(s[0]=='Q'){ printf("%d\n",query(u)); }else{ scanf("%d%d",&d,&v); update(u,d,v); } } return 0; }
T4 bzoj4012
在二分那里卡了好久,一气之下手打二分。(silly STL!) 一对比,树剖+主席树真的是太优越了!
#include<cstdio> #include<vector> #include<algorithm> using namespace std; typedef long long ll; const int N=150005; int n,m,u,v,d,l,r,mod,cnt,a ,head ,to[N*2],nxt[N*2],dd[N*2]; int idx,dep ,dfn[N*2],pos[N*2],f[N*2][20],Log2[N*2]; int mi,size,rt,siz ,fa ; ll ans,dis ; bool vis ; struct data{ int col; ll d,sum; bool operator < (const data &a) const{ return col==a.col?d<a.d:col<a.col; } }; vector<data> V[2] ; void adde(int u,int v,int d){ to[++cnt]=v; nxt[cnt]=head[u]; dd[cnt]=d; head[u]=cnt; } void dfs(int pre,int u){ dfn[u]=++idx; pos[idx]=u; siz[u]=1; int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(v!=pre){ dep[v]=dep[u]+1; dis[v]=dis[u]+dd[i]; dfs(u,v); pos[++idx]=u; siz[u]+=siz[v]; } } } void st(){ for(int i=1;i<=idx;i++){ f[i][0]=pos[i]; } for(int j=1;j<=20;j++){ for(int i=1;i+(1<<j)-1<=idx;i++){ if(dep[f[i][j-1]]<dep[f[i+(1<<(j-1))][j-1]]){ f[i][j]=f[i][j-1]; }else{ f[i][j]=f[i+(1<<(j-1))][j-1]; } } } } int lca(int u,int v){ if(dfn[v]<dfn[u]){ swap(u,v); } int k=Log2[dfn[v]-dfn[u]]; if(f[dfn[u]][k]<f[dfn[v]-(1<<k)+1][k]){ return f[dfn[u]][k]; }else{ return f[dfn[v]-(1<<k)+1][k]; } } ll dist(int u,int v){ return dis[u]+dis[v]-2*dis[lca(u,v)]; } void dfsroot(int pre,int u){ siz[u]=1; int v,mx=0; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]&&v!=pre){ dfsroot(u,v); siz[u]+=siz[v]; mx=max(mx,siz[v]); } } mx=max(mx,size-siz[u]); if(mx<mi){ mi=mx; rt=u; } } void update(int rt,int pre,int u,int dis,int md){ V[md][rt].push_back((data){a[u],dis,0}); int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]&&v!=pre){ update(rt,u,v,dis+dd[i],md); } } } void build(int pre,int u){ vis[u]=true; fa[u]=pre; update(u,0,u,0,0); int v; for(int i=head[u];i;i=nxt[i]){ v=to[i]; if(!vis[v]){ mi=size=siz[v]; dfsroot(u,v); update(rt,u,v,dd[i],1); build(u,rt); } } } int find(vector<data> &a,data x){ int l=0,r=a.size()-1,mid; while(l<r){ mid=(l+r+1)/2; if(a[mid]<x){ l=mid; }else{ r=mid-1; } } return l; } ll query(int u,int l,int r){ int L=find(V[0][u],(data){l,-1,0}),R=find(V[0][u],(data){r,(ll)1e18,0}); ll ans=V[0][u][R].sum-V[0][u][L].sum,d; for(int i=u;fa[i];i=fa[i]){ d=dist(fa[i],u); L=find(V[0][fa[i]],(data){l,-1,0}),R=find(V[0][fa[i]],(data){r,(ll)1e18,0}); ans+=V[0][fa[i]][R].sum-V[0][fa[i]][L].sum+d*(R-L); L=find(V[1][i],(data){l,-1,0}),R=find(V[1][i],(data){r,(ll)1e18,0}); ans-=V[1][i][R].sum-V[1][i][L].sum+d*(R-L); } return ans; } int main(){ for(int i=2;i<=300000;i++){ Log2[i]=Log2[i/2]+1; } scanf("%d%d%d",&n,&m,&mod); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } for(int i=1;i<n;i++){ scanf("%d%d%d",&u,&v,&d); adde(u,v,d); adde(v,u,d); } dfs(0,1); st(); mi=size=n; dfsroot(0,1); build(0,rt); for(int i=1;i<=n;i++){ for(int j=0;j<=1;j++){ V[j][i].push_back((data){-1,0,0}); sort(V[j][i].begin(),V[j][i].end()); if(V[j][i].size()){ V[j][i][0].sum=V[j][i][0].d; } for(int k=1;k<V[j][i].size();k++){ V[j][i][k].sum=V[j][i][k-1].sum+V[j][i][k].d; } } } while(m--){ scanf("%d%d%d",&u,&l,&r); l=(l+ans)%mod; r=(r+ans)%mod; if(l>r){ swap(l,r); } printf("%lld\n",ans=query(u,l,r)); } return 0; }
相关文章推荐
- 【Learning】倍增求LCA题目汇总
- 【Learning】虚树题目汇总
- 【Learning】 动态树分治
- 【Learning】Link-Cut Tree 题目汇总
- 【learning】树形dp题目汇总
- C++面试常见题目问与答(汇总一)
- C/C++ 笔试、面试题目大汇总
- SAT历年真题之:作文题目汇总(一)
- C/C++ 笔试、面试题目大汇总(转)
- (分治)分治法 及 题目
- 组原题目汇总
- Kaggle竞赛题目之——Titanic: Machine Learning from Disaster
- 各类深搜题目汇总
- 计算机网络---基础题目汇总七
- SQL面试题目汇总
- [置顶] 前端重点题目汇总
- 机器学习题目汇总一
- 操作系统---基础题目汇总六
- Leetcode题目解答汇总
- →『C/C++ 笔试、面试题目大汇总[31-40]』