zoukankan      html  css  js  c++  java
  • Wannafly Day2 E 阔力梯的树(树上启发式合并)

    题目链接:https://ac.nowcoder.com/acm/contest/4010/E

    题目分析:

    错误解法:看一眼就知道要用set,于是我一开始非常莽的跑了一发O(n*n*logn)的假算法,过了70%的数据,就是对于每次操作,新添加的树合并到重儿子上,合并完之后,用vector把set里的元素全部复制(提取)出来,再O(n)扫一发vector序列,想想吧,1e5大小的肯定爆TLE了.

     1 #include<bits/stdc++.h>
     2 #define ll long long
     3 #define rep(i,a,n) for(int i=a;i<=n;i++)
     4 #define per(i,n,a) for(int i=n;i>=a;i--)
     5 #define endl '
    '
     6 #define eps 0.000000001
     7 #define pb push_back
     8 #define mem(a,b) memset(a,b,sizeof(a))
     9 #define IO ios::sync_with_stdio(false);cin.tie(0);
    10 using namespace std;
    11 const int INF=0x3f3f3f3f;
    12 const ll inf=0x3f3f3f3f3f3f3f3f;
    13 const int mod=1e9+7;
    14 const int maxn=1e5+5;
    15 int tot,head[maxn];
    16 struct E{
    17     int to,next;
    18 }edge[maxn<<1];
    19 void add(int u,int v){
    20     edge[tot].to=v;
    21     edge[tot].next=head[u];
    22     head[u]=tot++;
    23 }
    24 int n;
    25 int siz[maxn],son[maxn],dep[maxn];
    26 void dfs1(int u,int f){
    27     dep[u]=dep[f]+1;
    28     siz[u]=1;
    29     for(int i=head[u];i!=-1;i=edge[i].next){
    30         int v=edge[i].to;
    31         if(v==f) continue;
    32         dfs1(v,u);
    33         siz[u]+=siz[v];
    34         if(siz[v]>siz[son[u]]) son[u]=v;
    35     }
    36 }
    37 int flag;set<int> s;ll ans[maxn];
    38 void count(int u,int f,int val){
    39     if(val==1) s.insert(u);
    40     else s.erase(u);
    41     for(int i=head[u];i!=-1;i=edge[i].next){
    42         int v=edge[i].to;
    43         if(v==f||v==flag) continue;
    44         count(v,u,val);
    45     }
    46 }
    47 void dfs(int u,int f,int keep){
    48     for(int i=head[u];i!=-1;i=edge[i].next){
    49         int v=edge[i].to;
    50         if(v==f||v==son[u]) continue;
    51         dfs(v,u,0);
    52     }
    53     if(son[u]){
    54         dfs(son[u],u,1);
    55         flag=son[u];
    56     }
    57     count(u,f,1);
    58     vector<int> vec;
    59     for(auto it:s) vec.push_back(it);
    60     ll sum=0;
    61     for(int i=0;i<vec.size()-1;i++){
    62         sum+=(vec[i+1]-vec[i])*(vec[i+1]-vec[i]);
    63     }
    64     ans[u]=sum;
    65     flag=0;
    66     if(!keep){
    67         count(u,f,-1);
    68     }
    69 }
    70 int main(){
    71     cin>>n;mem(head,-1);
    72     rep(i,2,n){
    73         int x;cin>>x;
    74         add(x,i);add(i,x);
    75     }
    76     dfs1(1,0);
    77     dfs(1,0,0);
    78     rep(i,1,n){
    79         cout<<ans[i]<<endl;
    80     }
    81 }
    View Code

    正确解法:借助树上启发式合并不断传递的思想,对于每次更新的一个数,我们都可以在logn的时间复杂度内解决,具体实现就是先二分找到这个操作数的位置,并取出其相邻的两个数,减去之前的贡献,累加上新增加的贡献即可完成贡献(这一步很妙!!我感觉可以出一下这方面的坑新生hhh),这样总的时间复杂度就是O(n*logn*logn)了。这里对STL中set容器的运用我又加深了一步嘻嘻

      1 #include<bits/stdc++.h>
      2 #define ll long long
      3 #define rep(i,a,n) for(int i=a;i<=n;i++)
      4 #define per(i,n,a) for(int i=n;i>=a;i--)
      5 #define endl '
    '
      6 #define eps 0.000000001
      7 #define pb push_back
      8 #define mem(a,b) memset(a,b,sizeof(a))
      9 #define IO ios::sync_with_stdio(false);cin.tie(0);
     10 using namespace std;
     11 const int INF=0x3f3f3f3f;
     12 const ll inf=0x3f3f3f3f3f3f3f3f;
     13 const int mod=1e9+7;
     14 const int maxn=1e5+5;
     15 int tot,head[maxn];
     16 struct E{
     17     int to,next;
     18 }edge[maxn<<1];
     19 void add(int u,int v){
     20     edge[tot].to=v;
     21     edge[tot].next=head[u];
     22     head[u]=tot++;
     23 }
     24 int n;
     25 int siz[maxn],son[maxn],dep[maxn];
     26 void dfs1(int u,int f){
     27     dep[u]=dep[f]+1;
     28     siz[u]=1;
     29     for(int i=head[u];i!=-1;i=edge[i].next){
     30         int v=edge[i].to;
     31         if(v==f) continue;
     32         dfs1(v,u);
     33         siz[u]+=siz[v];
     34         if(siz[v]>siz[son[u]]) son[u]=v; 
     35     }
     36 }
     37 int flag;set<int> s;ll ans[maxn],sum;
     38 void in(int num){
     39     set<int>::iterator it=s.lower_bound(num),start=s.begin(),end=s.end();
     40     end--;
     41     auto pre=it,next=it;
     42     if(pre!=start) pre--;
     43     if(next!=end) next++;
     44     if(it!=next&&it!=pre){
     45         sum-=1LL*(*next-*pre)*(*next-*pre);
     46         sum+=1LL*(*next-*it)*(*next-*it);
     47         sum+=1LL*(*it-*pre)*(*it-*pre);
     48     }
     49     else if(it==next&&it!=pre){
     50         sum+=1LL*(*it-*pre)*(*it-*pre);
     51     }
     52     else if(it==pre&&it!=next){
     53         sum+=1LL*(*next-*it)*(*next-*it);
     54     }
     55 }
     56 void out(int num){
     57     set<int>::iterator it=s.lower_bound(num),start=s.begin(),end=s.end();
     58     end--;
     59     auto pre=it,next=it;
     60     if(pre!=start) pre--;
     61     if(next!=end) next++;
     62     if(it!=next&&it!=pre){
     63         sum+=1LL*(*next-*pre)*(*next-*pre);
     64         sum-=1LL*(*next-*it)*(*next-*it);
     65         sum-=1LL*(*it-*pre)*(*it-*pre);
     66     }
     67     else if(it==next&&it!=pre){
     68         sum-=1LL*(*it-*pre)*(*it-*pre);
     69     }
     70     else if(it==pre&&it!=next){
     71         sum-=1LL*(*next-*it)*(*next-*it);
     72     }
     73 }
     74 void count(int u,int f,int val){
     75     if(val==1) s.insert(u),in(u);
     76     else out(u),s.erase(u);
     77     for(int i=head[u];i!=-1;i=edge[i].next){
     78         int v=edge[i].to;
     79         if(v==f||v==flag) continue;
     80         count(v,u,val);
     81     }
     82 }
     83 void dfs(int u,int f,int keep){
     84     for(int i=head[u];i!=-1;i=edge[i].next){
     85         int v=edge[i].to;
     86         if(v==f||v==son[u]) continue;
     87         dfs(v,u,0);
     88     }
     89     if(son[u]){
     90         dfs(son[u],u,1);
     91         flag=son[u];
     92     }
     93     count(u,f,1);
     94     ans[u]=sum;
     95     flag=0;
     96     if(!keep){
     97         count(u,f,-1);sum=0;
     98     }
     99 }
    100 int main(){
    101     cin>>n;mem(head,-1);
    102     rep(i,2,n){
    103         int x;cin>>x;
    104         add(x,i);add(i,x);
    105     }
    106     dfs1(1,0);
    107     dfs(1,0,0);
    108     rep(i,1,n){
    109         cout<<ans[i]<<endl;
    110     }
    111 }
    View Code
  • 相关阅读:
    jQuery EasyUI API 中文文档 数字框(NumberBox)
    jQuery EasyUI API 中文文档 数值微调器(NumberSpinner)
    jQuery EasyUI API 中文文档 日期时间框(DateTimeBox)
    jQuery EasyUI API 中文文档 微调器(Spinner)
    jQuery EasyUI API 中文文档 树表格(TreeGrid)
    jQuery EasyUI API 中文文档 树(Tree)
    jQuery EasyUI API 中文文档 属性表格(PropertyGrid)
    EntityFramework 数据操作
    jQuery EasyUI API 中文文档 对话框(Dialog)
    jQuery EasyUI API 中文文档 组合表格(ComboGrid)
  • 原文地址:https://www.cnblogs.com/Anonytt/p/13080989.html
Copyright © 2011-2022 走看看