zoukankan      html  css  js  c++  java
  • spoj COT2

    COT2 - Count on a tree II

    http://www.spoj.com/problems/COT2/

    You are given a tree with N nodes. The tree nodes are numbered from 1 to N. Each node has an integer weight.

    We will ask you to perform the following operation:

    • u v : ask for how many different integers that represent the weight of nodes there are on the path from u tov.

    Input

    In the first line there are two integers N and M. (N <= 40000, M <= 100000)

    In the second line there are N integers. The i-th integer denotes the weight of the i-th node.

    In the next N-1 lines, each line contains two integers u v, which describes an edge (u, v).

    In the next M lines, each line contains two integers u v, which means an operation asking for how many different integers that represent the weight of nodes there are on the path from u to v.

    Output

    For each operation, print its result.

    Example

    Input:
    8 2
    105 2 9 3 8 5 7 7
    1 2
    1 3
    1 4
    3 5
    3 6
    3 7
    4 8
    2 5
    7 8
    Output:
    4
    4
     

    题意:问树上两点间有多少不同的权值 

    树上莫队

    开始狂T,发现自己竟是按节点编号划分的块!!

    dfs分块。。

    #include<cmath>
    #include<cstdio>
    #include<algorithm>
    using namespace std;
    #define N 40001
    #define M 100001
    int n,m,siz,tmp;
    int hash[N],key[N];
    int front[N],to[N*2],nxt[N*2],tot;
    int fa[N],deep[N],id[N],son[N],bl[N],block[N];
    bool vis[N];
    int sum[N],ans[M];
    struct node
    {
        int l,r,id;
        bool operator < (node p) const
        {
            if(block[l]!=block[p.l]) return block[l]<block[p.l];
            return block[r]<block[p.r];
        }
    }e[M];
    int read(int &x)
    {
        x=0; char c=getchar();
        while(c<'0'||c>'9') c=getchar();
        while(c>='0'&&c<='9') { x=x*10+c-'0'; c=getchar(); }
    }
    void add(int x,int y)
    {
        to[++tot]=y; nxt[tot]=front[x]; front[x]=tot;
        to[++tot]=x; nxt[tot]=front[y]; front[y]=tot;
    }
    void dfs(int x)
    {
        son[x]++;
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==fa[x]) continue;
            deep[to[i]]=deep[x]+1;
            fa[to[i]]=x;
            dfs(to[i]);
            son[x]+=son[to[i]];
        }
    }
    void dfs2(int x,int top)
    {
        id[x]=++tot;
        bl[x]=top;
        block[x]=(tot-1)/siz+1;
        int y=0;
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==fa[x]) continue;
            if(son[to[i]]>son[y]) y=to[i];
        }
        if(!y) return;
        dfs2(y,top);
        for(int i=front[x];i;i=nxt[i])
        {
            if(to[i]==fa[x]||to[i]==y) continue;
            dfs2(to[i],to[i]);
        }
    }
    void point(int u)
    {
        if(vis[u]) tmp-=(!--sum[hash[u]]);
        else tmp+=(++sum[hash[u]]==1);
        vis[u]^=1;
    }
    void path(int u,int v)
    {
        while(u!=v)
        {
            if(deep[u]>deep[v]) point(u),u=fa[u];
            else point(v),v=fa[v];
        }
    }
    int get_lca(int u,int v)
    {
        while(bl[u]!=bl[v])
        {
            if(deep[bl[u]]<deep[bl[v]]) swap(u,v);
            u=fa[bl[u]];
        }
        return deep[u]<deep[v] ? u : v;
    }
    int main()
    {
        read(n);read(m);  siz=sqrt(n);
        for(int i=1;i<=n;i++) read(key[i]),hash[i]=key[i];
        sort(key+1,key+n+1);
        key[0]=unique(key+1,key+n+1)-(key+1);
        for(int i=1;i<=n;i++) hash[i]=lower_bound(key+1,key+key[0]+1,hash[i])-key;
        int x,y;
        for(int i=1;i<n;i++)
        {
            read(x); read(y);
            add(x,y);
        }
        tot=0;
        dfs(1);
        dfs2(1,1);
        for(int i=1;i<=m;i++)
        {
            read(e[i].l); read(e[i].r);
            e[i].id=i;
        }
        sort(e+1,e+m+1);
        int L=1,R=1,lca;
        for(int i=1;i<=m;i++)
        {
            if(id[e[i].l]>id[e[i].r]) swap(e[i].l,e[i].r);
            path(L,e[i].l);
            path(R,e[i].r);
            lca=get_lca(e[i].l,e[i].r);
            point(lca);
            ans[e[i].id]=tmp;
            point(lca);
            L=e[i].l; R=e[i].r;
        }
        for(int i=1;i<=m;i++) printf("%d
    ",ans[i]);
    }
     
  • 相关阅读:
    【Android N 7.1.1】 屏幕亮和灭的处理地方
    Android 测量调用方法耗时的方法
    【Android M】获取屏幕锁定的相关信息:“无”,“滑动”,“PIN码”,"图案","密码"
    【Android N 7.1.1】 ActivityManagerService 获取cpu状态
    Android 判断当前是否在跑monkey测试
    【Android N 7.1.1】 锁屏之上显示Toast
    【Android N 7.1.1】 处于锁屏界面时可以转屏
    【Android N 7】使用量统计usagestats
    #### 批处理命令 获取当前目录下所有文件的路径
    Linux命令 swap:内存交换空间
  • 原文地址:https://www.cnblogs.com/TheRoadToTheGold/p/7071492.html
Copyright © 2011-2022 走看看