• BZOJ 1103 [POI2007]大都市meg(树状数组+dfs序)


    【题目链接】 http://www.lydsy.com/JudgeOnline/problem.php?id=1103

     

    【题目大意】

      给出一棵树,每条边的经过代价为1,现在告诉你有些路不需要代价了, 以A x y形式给出,表示x到y的路不再需要代价,同时还有查询操作W x, 查询1到x的路径需要多少代价。

    【题解】

      我们对树做一遍dfs,保存得到的dfs序,我们发现如果对dfs序列进行操作,

      对同一个点在进入位置设置1,出点位置设置-1, 那么查询1到x的代价就是dfs序到x入点位置的前缀和。 而对于取消代价的操作只要在出点位置+1,进入位置-1即可。

      单点修改,前缀查询可以用树状数组维护。

    【代码】

    #include <cstdio>
    #include <vector>
    using namespace std;
    const int N=500005;
    int x,y,T,n,m,top,c[N],st[N],f[N],l[N],r[N];
    vector<int> v[N];
    char op[10];
    void update(int x,int val){while(x<=n+n)c[x]+=val,x+=x&-x;}
    int query(int x){int res=-1;while(x)res+=c[x],x-=x&-x;return res;}
    void dfs(){
        st[++top]=1;
        while(top){
            int x=st[top],fx=f[top--];
            if(!l[x]){
                l[x]=++T;
                st[++top]=x;
                for(int i=0;i<v[x].size();i++){
                    if(v[x][i]==fx)continue;
                    st[++top]=v[x][i];
                    f[top]=x;
                }
            }else r[x]=++T;
        }
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<n;i++){
            scanf("%d%d",&x,&y);
            v[x].push_back(y);
            v[y].push_back(x);
        }dfs();
        for(int i=1;i<=n;i++){update(l[i],1);update(r[i],-1);}
        scanf("%d",&m);
        for(int i=1;i<n+m;i++){
            scanf("%s",op);
            if(op[0]=='A'){
                scanf("%d%d",&x,&y);
                update(l[y],-1);update(r[y],1);
            }else{
                scanf("%d",&x);
                printf("%d
    ",query(l[x]));
            }
        }return 0;
    }
    

      

  • 相关阅读:
    关联规则算法---Eclat算法
    Apriori算法第二篇----详细分析和代码实现
    scrapy框架初识
    git入门
    phantomjs的和谷歌浏览器的简单使用
    selenium模块的而简单使用
    代理ip的使用以及多进程爬取
    爬虫之re块解析
    爬虫初识和request使用
    xpath的基础使用
  • 原文地址:https://www.cnblogs.com/forever97/p/bzoj1103.html
Copyright © 2020-2023  润新知