【Learning】动态树分治题目汇总

这里主要是我的动态点分治的练习记录。
动态点分治就是可以修改信息的点分治。在机房里面观战学长互怼对方“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[N],to[N*2],nxt[N*2],dep[N],dfn[N],siz[N],Log2[N*2],pos[N*2],f[N*2][20];
int rt,mi,size,fa[N];
bool vis[N],ck[N];
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[N],C[N];
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[N],head[N],to[N*2],nxt[N*2],dfn[N],dep[N],siz[N],pos[N*2],f[N*2][25];
int rt,mi,size,fa[N],root[N][2],sumv[N*50],ch[N*50][2],dd[N];
bool vis[N];
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);
            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[N],to[N*2],nxt[N*2];
int idx,lg2[N*2],dfn[N],dep[N],siz[N],pos[N*2],f[N*2][20];
int mi,size,rt,fa[N];
int tot,root[N][2],tag[20000005],ch[20000005][2];
bool vis[N];
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[N],head[N],to[N*2],nxt[N*2],dd[N*2];
int idx,dep[N],dfn[N*2],pos[N*2],f[N*2][20],Log2[N*2];
int mi,size,rt,siz[N],fa[N];
ll ans,dis[N];
bool vis[N];
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][N];
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;
}
posted @ 2017-12-10 10:15  一剑霜寒十四洲  阅读(156)  评论(0编辑  收藏  举报