zoukankan      html  css  js  c++  java
  • 套题T5//各种树

    树(tree

    【题目描述】

    方方方种下了三棵树,一年后,第一棵树长出了n个节点。

    方方方会向你提出m个询问,每个询问给出两个数ij,你需要回答i号节点和j号节点在树上的距离。

    【输入数据】

    第一行两个整数nm。接下来n-1行每行两个整数ab表示一条边。接下来m行每行两个整数ij表示询问。

    【输出数据】

    m行,每行一个整数表示答案。

    【样例输入】

    3 2

    1 2

    1 3

    3 2

    1 1

    【样例输出】

    2

    0

    【数据范围】

    对于30%的数据,n,m<=1000

    对于100%的数据,n,m<=500000


    裸lca

    //lca教程 http://www.cnblogs.com/gc812/p/5839501.html

    这道题和lca的关系:
    对于这道题来说
    假设区间是f[i,j]
    最小值是__min
    答案就是f[i]-__min + f[j]-__min
    path就没什么用了

     先写RMQ 然后DFS的时候 这道题数据很大 保存成双向邻接表然后遍历一边就行了

    #include <cstdio>
    #include <vector>
    #include <cstring>
    #include <map>
    using namespace std;
    typedef vector<vector<int> > vv;
    void get_path(vector<int>& path,const vv& t,const int& cur,bool* vis,int depth,vector<int>& t_depth,map<int, int>& fr) {
        for (vector<int>::const_iterator i=t[cur].begin(); i!=t[cur].end(); ++i)
            if (!vis[*i]) {
                fr[*i]=path.size();
                path.push_back(*i);
                t_depth.push_back(depth+1);
                vis[*i]=1;
                get_path(path,t,*i,vis,depth+1,t_depth,fr);
                path.push_back(cur);
                t_depth.push_back(depth);
                vis[*i]=0;
            }
        return;
    }
    
    inline void swap(int& a,int& b) {
        int c=a;
        a=b;
        b=c;
    }
    
    class rmq {
        private:
            vector<vector<int> > f;
            void ini(const vector<int>&,const int&,const int&);
            int get_min(const int & a,const int& b) {
                return a<b?a:b;
            }
        public:
            rmq(const vector<int>& depth) {
                int n=depth.size();
                if (n>0) {
                    int k=0,temp=n-1;
                    while (temp!=0) {
                        ++k;
                        temp>>=1;
                    }
                    f=vector<vector<int> >(n,vector<int>(k+1));
                    ini(depth,n,k);
                }
            }
            int query(const int& l,const int& r);
    
    };
    
    void rmq::ini(const vector<int>& depth,const int& n,const int& k) {
        for (int i=0; i<n; ++i)
            f[i][0]=depth[i];
        for (int j=1; j<=k; ++j)
            for (int i=0; i<n; ++i)
                if ((i+(1<<j-1))<n)
                    f[i][j]=get_min(f[i][j-1],f[i+(1<<(j-1))][j-1]);
    }
    
    int rmq::query(const int& l,const int& r) {
    
        if (l==r)
            return f[l][0];
    
        int temp=r-l,k=0;
        while (temp!=0) {
            temp>>=1;
            ++k;
        }
        return get_min(f[l][k-1],f[r+1-(1<<(k-1))][k-1]);
    }
    
    int main() {
        int n,m;
        scanf("%d%d",&n,&m);
        vv t(n+1,vector<int>());
        for (int i=0; i<n-1; ++i) {
            int a,b;
            scanf("%d%d",&a,&b);
            t[a].push_back(b);
            t[b].push_back(a);
        }
        vector<int> path(1,1),t_depth(1,1);
        bool* vis=new bool[n+1];
        memset(vis,0,n+1);
        vis[1]=1;
        map<int, int> fr;
        fr[1]=0;
        get_path(path,t,1,vis,1,t_depth,fr);
        rmq RMQ(t_depth);
        for (int i=0; i<m; ++i) {
            int a,b;
            scanf("%d%d",&a,&b);
            int low=fr[a],high=fr[b];
            if (low>high)swap(low,high);
            int min=RMQ.query(low,high);
            printf("%d
    ",t_depth[fr[a]]-min+t_depth[fr[b]]-min);
        }
        return 0;
    }
    View Code

    树(tree2

    【题目描述】

    方方方种下了三棵树,两年后,第二棵树长出了n个节点,其中1号节点是根节点。

    方方方进行m次操作,每个操作为:

    1)给出两个数ix,将第i个节点的子树中,与i距离为斐波那契数的节点权值+x(包括i本身)。

    2)给出一个数i,求出第i个节点的子树中,与i距离为斐波那契数的节点的权值和(包括i本身)。

    【读入数据】

    第一行两个整数nm。接下来n-1行每行两个整数ab表示一条边。接下来m行每行第一个数表示操作类型,接下来12个数表示i (x)

    【读出数据】

    对于每个(2)操作,输出一行一个整数表示答案。

    【样例输入】

    5 3

    1 2

    2 3

    3 4

    4 5

    1 1 1

    1 2 2

    2 4

    【样例输出】

    1

    【数据范围】

    对于30%的数据,n,m<=1000

    对于100%的数据,n,m<=100000|x|<=10^9



    树(tree3

    【题目描述】

    方方方种下了三棵树,两年后,第二棵树长出了n个节点,其中1号节点是根节点。

    方方方使用魔法为每个节点按以下规则染色:

    (1) 每个节点为红色,黑色或白色。

    (2) 对于每个叶节点i,有ribiwi三个参数,满足ri+bi+wi=1。方方方分别以ribiwi的概率给i染上红色,黑色和白色。

    (3) 对于每个非叶节点,设它的子树大小为x,当它的子树中的其它x-1个节点都被染色后,对它进行染色。假设这x-1个节点分别有rbw个红色、黑色和白色,那么它被染成红色、黑色、白色的概率分别为r/(x-1)b/(x-1)w/(x-1)

    染色结束后,方方方按以下规则计算这棵树的魔法值:

    (1) 对于每个有序点对(i,j),如果它们的颜色集合为{红色,黑色}ij的祖先,魔法值+rb

    (2) 对于每个有序点对(i,j),如果它们的颜色集合为{红色,白色}ij的祖先,魔法值+rw

    (3) 对于每个有序点对(i,j),如果它们的颜色集合为{黑色,白色}ij的祖先,魔法值+bw

    你需要求出魔法值的期望对998244353取模的结果。

    【读入数据】

    第一行四个整数nrbrwbw,接下来n-1行每行两个整数ab表示一条边。接下来n行每行三个整数ribiwi,如果i是叶子节点,保证ri+bi+wi=1,否则ri=bi=wi=0

    【读出数据】

    输出魔法值的期望对998244353取模的结果。

    【样例读入】

    2 1 2 3

    1 2

    1 0 0

    499122177 499122177 0

    【样例输出】

    499122177

    【数据范围】

    对于10%的数据,n<=10

    对于30%的数据,n<=50

    对于另外20%的数据,rb=rw=bw

    对于再另外20%的数据,每个叶子节点i满足ri=bi=wi

    对于100%的数据,n<=10000<=rb,rw,bw,ri,bi,wi<998244353


  • 相关阅读:
    EasyUI应用总结
    ExcelUtil
    搭建Easyui环境在Myeclipse或Eclipse中
    Easyui Datagrid 如何实现后台交互显示用户数据列表
    mybatis整合ehcache
    Flynn初步:基于Docker的PaaS台
    Following unknown configure options were used:--enable-fpm
    Android决议具体解释
    cocos2dx lua
    Android 建立View 圆角
  • 原文地址:https://www.cnblogs.com/gc812/p/5839239.html
Copyright © 2011-2022 走看看