poj 3321 Apple Trie

简介:

/*
  poj 3321 Apple Trie
  这道题的关键是如何将一个树建成一个一维数组利用树状数组来解题!
  可以利用dfs()来搞定,我们在对一个节点深搜后,所经过的节点的数目就是该节点的子树的数目
  所以我们利用start[i]数组来记录 i 节点在一维数组的起始位置, 而end[i]则是记录i节点所有孩子
  节点最后一个孩子节点在数组的位置,那么end[i]-start[i]+1,就是 i 节点(包括自身)和其所有孩子节点的
  数目。数组建好了,那么最后就是套用树状数组模板进行求解了!
*/
#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#define N 100005
using namespace std;
class node
{
public :
    int k;
    node *next;
    node()
    {
        next=NULL;
    }
};
 
node trie[N];
//trie[i]记录的是所有是 i 节点 孩子节点组成的链表的头部
int C[N], num[N];
int start[N], end[N];
int cnt, n;
 
void dfs(int cur)
{
    start[cur]=cnt;
    if(trie[cur].next==NULL)
    {
        end[cur]=cnt;
        return;
    }
    for(node *p=trie[cur].next; p!=NULL; p=p->next)//遍历cur节点的所有孩子节点
    {
        ++cnt;
        dfs(p->k);
    }
    end[cur]=cnt;//深搜之后得到的cnt值就是cur节点最后一个孩子在一维数组中的位置
}
 
int lowbit(int x)
{
   return x&(-x);
}
 
void init(int p, int k)
{
   int i;
   num[p]=k;
   for(i=p-lowbit(p)+1; i<=p; ++i)
      C[p]+=num[i];
}
 
int getSum(int p)
{
    int s=0;   
    while(p>0)
    {
        s+=C[p];
        p-=lowbit(p);
    }
    return s;
}
 
void update(int p, int k)
{
    while(p<=n)
    {
        C[p]+=k;
        p+=lowbit(p);
    }
}
 
 
int main()
{
   int i, u, v, m;
   char ch[2];
   int f;
   while(scanf("%d", &n)!=EOF)
   {
      cnt=1;
      memset(C, 0, sizeof(C));
      for(i=1; i<n; ++i)
      {
          scanf("%d%d", &u, &v);
          node *p=new node();
          p->k=v;
          p->next=trie[u].next;
          trie[u].next=p;
      }
      dfs(1);
      for(i=1; i<=n; ++i)
         init(i, 1);
      scanf("%d", &m);
      while(m--)
      {
     scanf("%s%d", ch, &f);
     if(ch[0]=='C')
     {
         if(num[f]==1)
           {
              update(start[f], -1);
              num[f]=0;
           }
         else
           {
              update(start[f], 1);
              num[f]=1;
           }
     }
     else
        printf("%d\n", getSum(end[f])-getSum(start[f]-1));
      }
   }
   return 0;
}<br><br>



/*<br>   这道题利用二维数组建图也可以过,不过数组的大小还真是难以捉摸....<br>*/<br>#include<iostream>
#include<vector>
#include<cstring>
#include<cstdio>
#define N 100005
using namespace std;
int node[N][100];
int C[N], num[N];
int start[N], end[N];
int cnt, n;
 
void dfs(int cur)
{
    int sz=node[cur][0];
    start[cur]=cnt;
    if(sz==0)
    {
        end[cur]=cnt;
        return;
    }
    for(int i=1; i<=sz; ++i)
    {
        ++cnt;
        dfs(node[cur][i]);
    }
    end[cur]=cnt;
}
 
int lowbit(int x)
{
   return x&(-x);
}
 
void init(int p, int k)
{
   int i;
   num[p]=k;
   for(i=p-lowbit(p)+1; i<=p; ++i)
      C[p]+=num[i];
}
 
int getSum(int p)
{
    int s=0;   
    while(p>0)
    {
        s+=C[p];
        p-=lowbit(p);
    }
    return s;
}
 
void update(int p, int k)
{
    while(p<=n)
    {
        C[p]+=k;
        p+=lowbit(p);
    }
}
 
 
int main()
{
   int i, u, v, m;
   char ch[2];
   int f;
   while(scanf("%d", &n)!=EOF)
   {
      cnt=1;
      for(i=1; i<=n; ++i)
         node[i][0]=0;
      memset(C, 0, sizeof(C));
      for(i=1; i<n; ++i)
      {
          scanf("%d%d", &u, &v);
          node[u][++node[u][0]]=v;
      }
      dfs(1);
      for(i=1; i<=n; ++i)
         init(i, 1);
      scanf("%d", &m);
      while(m--)
      {
     scanf("%s%d", ch, &f);
     if(ch[0]=='C')
     {
         if(num[f]==1)
           {
              update(start[f], -1);
              num[f]=0;
           }
         else
           {
              update(start[f], 1);
              num[f]=1;
           }
     }
     else
        printf("%d\n", getSum(end[f])-getSum(start[f]-1));
      }
   }
   return 0;
}


目录
相关文章
|
8月前
|
存储 C++
leetcode-208:实现 Trie (前缀树/字典树)
leetcode-208:实现 Trie (前缀树/字典树)
61 0
POJ 3494 Largest Submatrix of All 1’s(单调栈)
POJ 3494 Largest Submatrix of All 1’s(单调栈)
|
存储 算法
Trie(一)
文章目录 前言 一、Trie 二、例题,代码 1.AcWing 835. Trie字符串统计 关于本题: AC代码 2.AcWing 143. 最大异或对 关于本题 AC代码 三、时间复杂度
118 0
Trie(一)
|
算法
Trie(二)
AcWing 835. Trie字符串统计
147 0
Trie(二)
[路飞]_leetcode-144-二叉树的前序遍历-迭代算法
leetcode-144-二叉树的前序遍历-迭代算法
|
存储 C++
【LeetCode208】实现Trie(前缀树)
这里的前缀树,即“二十六叉树”,但是对于每个结点(对象),我们可以隐性存储一个字符——每个结点(对象)含有一个size为26的指针数组。接着就从根结点开始遍历判
131 0
【LeetCode208】实现Trie(前缀树)