套题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\n",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

 


 

posted @ 2016-09-04 14:23  pandaB  阅读(171)  评论(0编辑  收藏  举报