夏夜、

心若平似镜、何题不AC。

UVA 1357 Cells

考虑一颗普通的树,DFS一遍后得到每个点的DFS前序历遍顺序值dfsid[] ,和以改点为根的子树的总结点数num[]。

(比如第一组样例dfsid[]={0,1,6,8,2,3,7,9,4,5}   num[]={10,5,2,2,1,3,1,1,1,1});

那么要判断a是否为b的祖先,只要满足dfsid[a]<dfsid[b]<dfsid[a]+num[a]

因为这题的结点最多会有2000W,所以不能建完整的树,只能建n个结点,否则超时。

由于编号大于n的结点肯定是叶节点,我们可以通过求son数组(每个结点的儿子数)的前缀和,然后二分查找找到b的父亲结点,再判断。

大概步骤就是

1.BFS建树,只建n个结点。

2.DFS,求dfsid[] 和num[] 数据量大,用栈模拟递归

3.求son[]的前缀和

4.判断每对a,b.     会有a==b的数据

 

总复杂度O(mlogn)

//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<iostream>
#include<sstream>
#include<cmath>
#include<climits>
#include<string>
#include<map>
#include<queue>
#include<vector>
#include<stack>
#include<set>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> pii;
#define pb(a) push(a)
#define INF 0x1f1f1f1f
#define lson idx<<1,l,mid
#define rson idx<<1|1,mid+1,r
#define PI  3.1415926535898
template<class T> T min(const T& a,const T& b,const T& c) {
    return min(min(a,b),min(a,c));
}
template<class T> T max(const T& a,const T& b,const T& c) {
    return max(max(a,b),max(a,c));
}
void debug() {
#ifdef ONLINE_JUDGE
#else

    freopen("d:\\in1.txt","r",stdin);
    freopen("d:\\out1.txt","w",stdout);
#endif
}
int getch() {
    int ch;
    while((ch=getchar())!=EOF) {
        if(ch!=' '&&ch!='\n')return ch;
    }
    return EOF;
}

const int maxn=300200;
vector<int> g[maxn];
int n;
int son[maxn];
int dfsid[maxn];
int num[maxn];

struct stacknode
{
    int u,i;
};
int dfs()
{
    int dfs_clock=0;
    stack<stacknode> st;
    st.push((stacknode){0,0});
    while(!st.empty())

    {
        stacknode x=st.top();st.pop();
        if(x.i==0){num[x.u]=1;dfsid[x.u]=dfs_clock++;}
        if(x.i<g[x.u].size())
        {
            x.i++;
            st.push(x);
            st.push((stacknode){g[x.u][x.i-1],0});
        }else
        {
            for(int i=0;i<g[x.u].size();i++)
                num[x.u]+=num[g[x.u][i]];
        }
    }
}
void build()
{
    int num=1;
    queue<int> q;
    q.push(0);
    while(!q.empty())
    {
        int x=q.front();q.pop();
        g[x].clear();
        if(x==n-1)return ;
        if(num>=n)continue;
        for(int i=1;i<=son[x];i++)
        {
            g[x].push_back(num);
            q.push(num++);
            if(num>=n)break;
        }
    }
}
int main()
{
    int t;
    scanf("%d",&t);
    for(int ca=1;ca<=t;ca++)
    {
        scanf("%d",&n);
        for(int i=0;i<n;i++)
            scanf("%d",&son[i]);
        build();
        dfs();
        for(int i=1;i<n;i++)
            son[i]+=son[i-1];
        int m;
        scanf("%d",&m);
        printf("Case %d:\n",ca);
        for(int i=1;i<=m;i++)
        {
            int a,b;
            scanf("%d%d",&a,&b);
            if(a==b)
            {
                printf("No\n");continue;
            }
            if(b>=n)
                b=lower_bound(son,son+n,b)-son;
            if(a<n&&dfsid[a]+num[a]>dfsid[b]&&dfsid[b]>=dfsid[a])
                printf("Yes\n");
            else printf("No\n");
        }
        if(ca!=t)printf("\n");
    }
    return 0;
}
View Code

 

posted on 2014-03-23 23:12  BMan、  阅读(266)  评论(0编辑  收藏  举报

导航