hdu 5877 离散化+树状数组+dfs序

来源:互联网 发布:逆战瞬狙数据 编辑:程序博客网 时间:2024/05/28 18:45

点击打开链接

参考点击打开链接

第一个要求u 是v 的祖先,那么可以dfs,遍历到v时,要使上方的都是满足第一条件的u,即遍历完某个节点u的子树时,这时u不可能是任何节点的祖先 删除u的影响,这样就能保证所有有影响的都是祖先。要求w[u]*w[v]<=k,那么到v的时候,所有小于等于k/w[v]的u都满足,可以想到树状数组。结点的值最大10亿,肯定要离散化,离散化的时候要把k/w[v]加进去一起离散。

#include <iostream>#include <cstring>#include <algorithm>#include <vector>#include <cstdio>using namespace std;const int inf=1<<20;const int M = 1e6+5;vector<int> e[M];int vis[M];int in[M];//in[i]为0的为root long long n,k;long long a[M*2];long long c[M<<1];long long  ans,data[2*M];int lowbit(int x){    return x&(-x);}void update(int x,int val){    while(x<2*n)    {        c[x]+=val;        x+=lowbit(x);//往右上走     }}int sum(int x){    int s=0;    while(x>0)    {        s+=c[x];        x-=lowbit(x);    }    return s;}void dfs(int rt){    vis[rt]=1;            ans+=sum(a[rt+n]);//在它之前进入的都为它的祖先(兄弟节点在遍历完之后已经删除)       update(a[rt],1);     //au*av<=k  祖先节点要满足au<=k/a[v]     for(int i=0;i<e[rt].size();i++)    {        int son=e[rt][i];        if(!vis[son])        {            dfs(son);        }    }    update(a[rt],-1);//该节点的子树全都遍历完了 该节点不是任何节点的祖先时 删除该节点的值 }void prepare(long long *x) //离散化模板 {      for(int i=1;i<=2*n;i++) data[i]=x[i];      sort(data+1,data+2*n+1);      int m=unique(data+1,data+2*n+1)-data-1;       for(int i=1;i<=2*n;i++) x[i]=lower_bound(data+1,data+m+1,x[i])-data;  }  int main(){    int t;    cin>>t;    while(t--)    {    cin>>n>>k;        ans=0;        memset(in,0,sizeof(in));        memset(c,0,sizeof(c));        memset(vis,0,sizeof(vis));        for(int i=1;i<=n;i++)        {            e[i].clear();        }        for(int i=1;i<=n;i++)        {            scanf("%lld",&a[i]);              if(a[i]==0)              a[i+n]=M;              else            a[i+n]=k/a[i];                                                   }        prepare(a);//数据a[i]<=10^9 n<=10^5 数据离散化使a[i]的范围中10^5内                     //使得树状数组的空间不溢出                    for(int i=1;i<=n-1;i++)        {            int u,v;            scanf("%d%d",&u,&v);            e[u].push_back(v);            in[v]++;                }        int root;        for(int i=1;i<=n;i++)        {            if(!in[i])            {                root=i;                break;            }        }        dfs(root);        cout<<ans<<endl;    }    return 0; } 


0 0
原创粉丝点击