• E


    题目链接:

    E - Problem E. Split The Tree

     HDU - 6504 

    题目大意:给你一个树,以及这棵树构成的边,允许你删除一条边,然后问你形成的两颗子树中不同的数的总和。

    具体思路:首先对于莫队的话,我们将这棵树转换成dfs序。1 2 3 4 ,当前是有四个节点,然后我们保存每个节点为根时子树的dfs序范围,每一次删除一条边,当前分成了两棵子树,然后第一棵子树的范围是2~3,第二棵子树是1 4,我们具体计算的时候,先统一算出1 2 3 4 所有的不同的数的总的个数。然后查询2 3 区间的时候,总的区间减去2 3 这段区间里面的不同的数的个数,然后剩下的就变成1 4 的不同的数的个数,然后我们再开一个区间保存2 3 这段区间里面不同的数的个数。两个加起来就是去除当前边的总的子树中不同的数的总和。

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #  define ll long long
     4 const int maxn = 1e5 +100;
     5 int n,tmp;
     6 int val[maxn];
     7 int vistot[maxn],vispart[maxn];
     8 vector<int>Edge[maxn];
     9 int lt[maxn],rt[maxn],Hash[maxn];
    10 int dfsnum;
    11 void init(int n){
    12 dfsnum=0;
    13 for(int i=0;i<=n;i++){Edge[i].clear();}
    14 memset(vistot,0,sizeof(vistot));
    15 memset(vispart,0,sizeof(vispart));
    16 }
    17 void dfs(int u,int fa){
    18 lt[u]=++dfsnum;
    19 Hash[dfsnum]=u;
    20 for(int i=0;i<Edge[u].size();i++){
    21 int to=Edge[u][i];
    22 if(to==fa)continue;
    23 dfs(to,u);
    24 }
    25 rt[u]=dfsnum;
    26 }
    27 struct node{
    28 int lt,rt,pos;
    29 node(){}
    30 node(int xx,int yy,int zz){lt=xx,rt=yy,pos=zz;}
    31 bool friend operator < (node t1,node t2){
    32 if(t1.pos==t2.pos)return t1.rt<t2.rt;
    33 return t1.pos<t2.pos;
    34 }
    35 }q[maxn];
    36 void update(int pos,int type,int &tot,int &part){
    37 int tmp=val[Hash[pos]];
    38 vispart[tmp]+=type;
    39 if(vispart[tmp]==1&&type==1){part++;}
    40 if(vispart[tmp]==0&&type==-1){part--;}
    41 type*=-1;
    42 vistot[tmp]+=type;
    43 if(vistot[tmp]==1&&type==1){tot++;}
    44 if(vistot[tmp]==0&&type==-1){tot--;}
    45 }
    46 int main(){
    47 while(~scanf("%d",&n)){
    48 init(n);
    49 for(int i=2;i<=n;i++){
    50 scanf("%d",&tmp);
    51 Edge[tmp].push_back(i);
    52 }
    53 int num=0;
    54 for(int i=1;i<=n;i++){
    55 scanf("%d",&val[i]);
    56 vistot[val[i]]++;
    57 if(vistot[val[i]]==1)num++;
    58 }
    59 dfs(1,-1);
    60 int block=(int)sqrt(n);
    61 for(int i=1;i<=n;i++){
    62 q[i]=node(lt[i],rt[i],(lt[i]-1)/block+1);
    63 }
    64 sort(q+1,q+n+1);
    65 int l=1,r=0,tot=num,part=0;
    66 int maxx=0;
    67 for(int i=1;i<=n;i++){
    68 while(l<q[i].lt)update(l,-1,tot,part),l++;
    69 while(l>q[i].lt)l--,update(l,1,tot,part);
    70 while(r<q[i].rt)r++,update(r,1,tot,part);
    71 while(r>q[i].rt)update(r,-1,tot,part),r--;
    72 maxx=max(maxx,tot+part);
    73 }
    74 printf("%d
    ",maxx);
    75 }
    76 }
    莫队

    对于树状数组:我们将这个区间扩大一倍,1 2 3 4 5 6 7 8,这里的5 6 7 8 保存的值还是1 2 3 4 所对应的。不过就是在查询2 3 区间的时候,我们再查询4 5 这个区间就能够求出当前的答案了。

    这样就能保证所求的区间是连续的了。

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #  define ll long long
      4 const int maxn = 2e5 +100;
      5 int n,tmp;
      6 vector<int>Edge[maxn];
      7 int val[maxn];
      8 int lt[maxn],rt[maxn];
      9 int dfsnum;
     10 int Hash[maxn];
     11 int vis[maxn],ans[maxn];
     12 int tree[maxn];
     13 void init()
     14 {
     15     dfsnum=0;
     16     for(int i=0;i<=n;i++){Edge[i].clear();}
     17 }
     18 void dfs(int u)
     19 {
     20     lt[u]=++dfsnum;
     21     Hash[dfsnum]=Hash[dfsnum+n]=u;
     22     for(int i=0; i<Edge[u].size(); i++)
     23     {
     24         int to=Edge[u][i];
     25         dfs(to);
     26     }
     27     rt[u]=dfsnum;
     28 }
     29 struct node
     30 {
     31     int lt,rt,id;
     32     node() {}
     33     node(int xx,int yy,int zz)
     34     {
     35         lt=xx,rt=yy,id=zz;
     36     }
     37     bool friend operator < (node t1,node t2)
     38     {
     39         if(t1.rt!=t2.rt)
     40             return t1.rt<t2.rt;
     41         return t1.lt<t2.lt;
     42     }
     43 } q[maxn];
     44 int lowbit(int t){
     45 return t&-t;
     46 }
     47 void add(int pos,int type)
     48 {
     49     while(pos<=2*n)
     50     {
     51         tree[pos]+=type;
     52         pos+=lowbit(pos);
     53     }
     54 }
     55 int  ask(int pos)
     56 {
     57     int ans=0;
     58     while(pos)
     59     {
     60         ans+=tree[pos];
     61         pos-=lowbit(pos);
     62     }
     63     return ans;
     64 }
     65 int main()
     66 {
     67     while(~scanf("%d",&n))
     68     {
     69         int tmp;
     70         init();
     71         for(int i=2; i<=n; i++)
     72         {
     73             scanf("%d",&tmp);
     74             Edge[tmp].push_back(i);
     75         }
     76         for(int i=1; i<=n; i++)
     77         {
     78             scanf("%d",&val[i]);
     79             val[i+n]=val[i];
     80         }
     81         dfs(1);
     82         for(int i=1; i<=2*n; i++)
     83         {
     84             vis[i]=0;
     85             ans[i]=0;
     86             tree[i]=0;
     87         }
     88         int tot=0;
     89         for(int i=1; i<=n; i++)
     90         {
     91             if(lt[i]==1)
     92                 continue;
     93             q[++tot]=node(lt[i],rt[i],i);
     94             q[++tot]=node(rt[i]+1,lt[i]+n-1,i);
     95         }
     96         sort(q+1,q+tot+1);
     97         int maxx=0,pre=1;
     98         for(int i=1; i<=tot; i++)
     99         {
    100             for(int j=pre; j<=q[i].rt; j++)
    101             {
    102                 int tmp=val[Hash[j]];
    103                 if(vis[tmp])
    104                     add(vis[tmp],-1);
    105                 vis[tmp]=j;
    106                 add(vis[tmp],1);
    107             }
    108             pre=q[i].rt+1;
    109             ans[q[i].id]+=ask(q[i].rt)-ask(q[i].lt-1);
    110             maxx=max(maxx,ans[q[i].id]);
    111         }
    112         printf("%d
    ",maxx);
    113     }
    114     return 0;
    115 }
    树状数组
  • 相关阅读:
    转载 自定义ListView背景
    Android 在模拟器上创建sd卡
    转载 Android TextView加下划线
    转载 Dom4j生成xml
    转载 在Struts2中使用servlet 配置问题
    android开发不错的地方
    bat demo1自定义变量
    redhat 5下安装SVN
    linux 忘记root密码
    DEBUG Sigar no libsigarx86linux.so in java.library.path
  • 原文地址:https://www.cnblogs.com/letlifestop/p/10826804.html
Copyright © 2020-2023  润新知