• 洛谷 P2542 [AHOI2005]航线规划 树链剖分_线段树_时光倒流_离线


    Code:

    #include <map>
    #include <cstdio>
    #include <algorithm>
    #include <cstring>
    #include <string>
    using namespace std;
    
    void setIO(string a){
        freopen((a+".in").c_str(),"r",stdin);
        freopen((a+".out").c_str(),"w",stdout);
    }
    
    #define N 30005
    #define Q 40005
    #define M 100005
    
    int n,m,cnt=1;
    int head[N];
    int to[M<<1];
    int nex[M<<1];
    
    int siz[N];
    int f[N];
    int son[N];
    int dep[N];
    int uu[M<<1];
    int vv[M<<1];
    bool tag[M<<1];
    bool vis[N];
    
    void addedge(int u,int v){
        nex[++cnt]=head[u],head[u]=cnt,to[cnt]=v;
        uu[cnt]=u,vv[cnt]=v;
    }
    
    void dfs1(int u,int fa,int depth){
        siz[u]=1,f[u]=fa,vis[u]=1,dep[u]=depth+1;
        for(int v=head[u];v;v=nex[v]){
            if(!vis[to[v]]&&to[v]!=fa) {
                tag[v]=tag[v^1]=1;
                dfs1(to[v],u,depth+1);
                siz[u]+=siz[to[v]];
                if(siz[to[v]]>siz[son[u]]) son[u]=to[v];
            }
        }
    }
    
    int A[N];
    int top[N];
    int cnt2=0;
    
    void dfs2(int u,int tp){
        top[u]=tp;
        A[u]=++cnt2;
        if(son[u])dfs2(son[u],tp);
        for(int v=head[u];v;v=nex[v])
            if(to[v]!=son[u]&&to[v]!=f[u]&&tag[v])dfs2(to[v],to[v]);
        //if(!son[u]) son[u]=u;
    }
    
    int sumv[N<<2];
    int lazy[N<<2];
    
    #define lson (o<<1)
    #define rson (o<<1)|1
    
    void pushup(int o){
        sumv[o]=sumv[lson]+sumv[rson];
        if(lazy[lson]&&lazy[rson]) lazy[o]=1,sumv[o]=0;
    }
    void build(int l,int r,int o){
        if(l>r)return;
        if(l==r) {
            sumv[o]=1;
            if(l==1)sumv[o]=0;
            return;
        }
        int mid=(l+r)>>1;
        build(l,mid,lson);
        build(mid+1,r,rson);
        pushup(o);
    }
    void modify(int l,int r,int o,int L,int R){
        if(l>r||r<L||l>R)return;
        if(lazy[o])return;
        if(l>=L&&r<=R){
            sumv[o]=0;
            lazy[o]=1;
            return;
        }
        int mid=(l+r)>>1;
        modify(l,mid,lson,L,R);
        modify(mid+1,r,rson,L,R);
        pushup(o);
    }
    int query(int l,int r,int o,int L,int R){
    
        if(lazy[o]||l>r||r<L||l>R)return 0;
        if(l>=L&&r<=R)return sumv[o];
        int mid=(l+r)>>1;
        return query(l,mid,lson,L,R)+query(mid+1,r,rson,L,R);
    }
    void update(int a,int b){
        while(top[a]!=top[b]){
            if(dep[top[a]]>dep[top[b]]) swap(a,b);
            modify(1,n,1,A[top[b]],A[b]),b=f[top[b]];
        }
        if(a==b)return ;
        if(dep[a]>dep[b]) swap(a,b); 
        modify(1,n,1,A[son[a]],A[b]);
    }
    
    int lookup(int a,int b){
        int sums=0;
        while(top[a]!=top[b]){
            if(dep[top[a]]>dep[top[b]]) swap(a,b);
            sums+=query(1,n,1,A[top[b]],A[b]);
            b=f[top[b]];
        }
        if(a==b) return sums;
        if(dep[a]>dep[b])swap(a,b);
        sums+=query(1,n,1,A[son[a]],A[b]);
        return sums;
    }
    
    struct Edge{
        int from,to,t;
        Edge(int from=0,int to=0,int t=0):from(from),to(to),t(t){}
    }edges[M];
    struct Ask{
        int a,b,c;
        Ask(int a=0,int b=0,int c=0):a(a),b(b),c(c){}
    }asks[Q];
    typedef pair<int,int> P;
    map<P,int>idx;
    int curr;
    int answer[Q];
    int cnans;
    int main(){
        //setIO("input");
        scanf("%d%d",&n,&m);
        for(int i=1;i<=m;++i){
            int a,b;
            scanf("%d%d",&a,&b);
            if(a>b)swap(a,b);
            edges[i]=Edge(a,b,0);
            idx[P(a,b)]=i;
        }
        while(1){
            int a,b,c;
            scanf("%d%d%d",&c,&b,&a);
            if(c==-1) break;
            if(a>b)swap(a,b);
            asks[++curr]=Ask(a,b,c);
            if(c!=1&&idx[P(a,b)]) edges[idx[P(a,b)]].t=1;
        }
        for(int i=1;i<=m;++i)
            if(edges[i].t!=1) 
                addedge(edges[i].from,edges[i].to),addedge(edges[i].to,edges[i].from);
        dfs1(1,0,0);
        dfs2(1,1);
        build(1,n,1);
        for(int i=2;i<=cnt;i+=2)
            if(!tag[i]){
                tag[i]=tag[i^1]=1;
                update(uu[i],vv[i]);
            }
            
        for(int i=curr;i>=1;--i)
        {
            if(asks[i].c==1) answer[++cnans]=lookup(asks[i].a,asks[i].b);
            else update(asks[i].a,asks[i].b);
        }
        for(int i=cnans;i>=1;--i) printf("%d
    ",answer[i]);
        return 0;
    }
    

      

  • 相关阅读:
    Java时间和时间戳的相互转换
    linux 通过pid 寻找程序路径的最简单命令(pwdx)
    Oracle--存储过程学习进阶
    经典sql总结(2)
    经典sql总结(1)
    类的初始化
    StringBuffer和String 的例子
    i=i++
    一个异常学习的好例子
    有空研究这篇http://blog.csdn.net/studyvcmfc/article/details/7720258 研究后写篇记录
  • 原文地址:https://www.cnblogs.com/guangheli/p/10078473.html
Copyright © 2020-2023  润新知