zoukankan      html  css  js  c++  java
  • 【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
    ",cnt-1);
                }else{
                    printf("%d
    ",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
    ",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
    ",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
    ",ans=query(u,l,r));
        }
        return 0;
    }
  • 相关阅读:
    MS CRM 2011插件调试工具
    MSCRM 相關 (到石頭居博客查看)
    es6 复习
    HTML阶段笔试题附答案
    CSS选择器
    jQuery 效果知识总结
    markdown基本语法
    HTML5给我们带来了什么?
    H5新增语义化标签
    c#中去掉字符串空格方法
  • 原文地址:https://www.cnblogs.com/2016gdgzoi471/p/9476909.html
Copyright © 2011-2022 走看看