zoukankan      html  css  js  c++  java
  • bzoj3697_FJ2014集训_采药人的路径_solution



    小道士的矫情之路;
    点分治,
    对于每个子树,处理其内经过根(重心)的路径,然后递归下一层子树;
    如何处理经过根的合法路径
    合法有两个要求;
    把输入的0改成-1后
    1.len=0;
    2.存在一个点i使被她分开的两个路径len均为零;
    在每次统计中我们可以dfs统计每条从根开始的路径(half_way),
    任意两条这样的路径拼成一条可能合法的路径;
    check合法?
    通过dfs;
    统计1,每个half_way的len
    还要统计,2,这个half_way上是否有一个点到half_way的终点(根之外的那个)的len=0;
    一,两个half_way的len加为0才可能合法;
    二,两个half_way中至少一个满足“有一个点到half_way的终点(根之外的那个)的len=0”;
    只要满足一&&二,则路径合法;(自己思考why?)
    1很好统计;
    关键是2;
    可以考虑维护一个桶;
    如果root到i的路径len=x,且桶x已经有值了,则i的二合法;(自己思考why?)
    由于这里细节极多,不好全部言明,故直接看代码:
     1 long long  get_ans(int root,int w){
     2     int i,j,k,l,kk,ll;
     3     long long ans=0;
     4     tot=0;if(w)map[zero]=1;
     5     dfs_ans(root,w,0);j=tot;
     6     sort(hw+1,hw+tot+1,cmp);
     7     for(i=1;i<j;i++){
     8         while(hw[i].d+hw[j].d>0&&i<j)
     9             j--;
    10         if(hw[i].d+hw[j].d==0){
    11             k=l=0;kk=i;ll=j;
    12             if(hw[i].d==0){
    13                 for(;i<=j;i++){
    14                     if(hw[i].can>=2)k++;
    15                     if(hw[i].can==1)l++;
    16                 }
    17                 ans+=(long long)(k+l)*(k+l-1)/2;
    18                 ans+=(long long)k*(ll-kk+1-l-k);
    19                 break;
    20             }
    21             while(1){
    22                 if(hw[i].can)k++;i++;
    23                 if(hw[i].d!=hw[i-1].d)break; 
    24             }
    25             while(1){
    26                 if(hw[j].can)l++;j--;
    27                 if(hw[j].d!=hw[j+1].d)break;
    28             }
    29             ans+=(long long)k*(ll-j-l)+l*(i-kk-k)+k*l;i--;
    30         }
    31     }
    32     if(w)map[zero]=0;
    33     return ans;
    34 }
    35 void dfs_ans(int now,int sum,int fa){
    36     hw[++tot].d=sum;
    37     hw[tot].can=map[zero+sum];
    38     map[zero+sum]++;
    39     for(int i=first[now];i;i=e[i].next)
    40         if(e[i].to!=fa&&!vis[e[i].to])
    41             dfs_ans(e[i].to,sum+e[i].d,now);
    42     map[zero+sum]--;
    43 }
    View Code

    由于这个操作是单次O(logn)的,于是我的做法比标解多了一个不大log;

    (标解O(nlogn),本人O(nlog²n),......大约是这样)

    之前桶没清干净,拍了好久没发现;

    总代码:

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 const int zero=100004;
      5 int n,tot;
      6 long long ans;
      7 struct half_way{
      8     int d,can;
      9 }hw[200010];
     10 int map[200010],vis[100010],size[100010],lsize[100010];
     11 struct ss{
     12     int to,next,d;
     13 }e[200010];
     14 int first[100010],num;
     15 bool cmp(half_way a,half_way b){
     16     return a.d<b.d;
     17 }
     18 void build(int ,int ,int );
     19 void part_dfs(int );
     20 void dfs_size(int ,int );
     21 int  dfs_root(int ,int ,int );
     22 long long  get_ans(int ,int );
     23 void dfs_ans(int ,int ,int );
     24 int main()
     25 {
     26     int i,j,k,l;
     27     scanf("%d",&n);
     28     for(i=1;i<n;i++){
     29         scanf("%d%d%d",&j,&k,&l);
     30         l=l?1:-1;
     31         build(j,k,l);
     32         build(k,j,l);
     33     }
     34     part_dfs(1);
     35     printf("%lld",ans);
     36     return 0;
     37 }
     38 void build(int f,int t,int wi){
     39     e[++num].next=first[f];
     40     e[num].to=t;e[num].d=wi;
     41     first[f]=num;
     42 }
     43 void part_dfs(int now){
     44     int i,root;
     45     dfs_size(now,0);
     46     root=dfs_root(now,0,now);
     47     ans+=get_ans(root,0);
     48     vis[root]=1;
     49     for(i=first[root];i;i=e[i].next)
     50         if(!vis[e[i].to]){
     51             ans-=get_ans(e[i].to,e[i].d);
     52             part_dfs(e[i].to);
     53         }
     54 }
     55 void dfs_size(int now,int fa){
     56     size[now]=1;
     57     for(int i=first[now];i;i=e[i].next)
     58         if(!vis[e[i].to]&&e[i].to!=fa){
     59             dfs_size(e[i].to,now);
     60             size[now]+=size[e[i].to];
     61         }
     62 }
     63 int dfs_root(int now,int fa,int r){
     64     int i,root=-1,wroot;
     65     lsize[now]=size[r]-size[now];
     66     for(i=first[now];i;i=e[i].next)
     67         if(!vis[e[i].to]&&e[i].to!=fa){
     68             if(size[e[i].to]>lsize[now])
     69                 lsize[now]=size[e[i].to];
     70             wroot=dfs_root(e[i].to,now,r);
     71             if(lsize[wroot]<lsize[root]||root==-1)
     72                 root=wroot;
     73         }
     74     if(lsize[now]<lsize[root]||root==-1)
     75         root=now;
     76     return root;
     77 }
     78 long long  get_ans(int root,int w){
     79     int i,j,k,l,kk,ll;
     80     long long ans=0;
     81     tot=0;if(w)map[zero]=1;
     82     dfs_ans(root,w,0);j=tot;
     83     sort(hw+1,hw+tot+1,cmp);
     84     for(i=1;i<j;i++){
     85         while(hw[i].d+hw[j].d>0&&i<j)
     86             j--;
     87         if(hw[i].d+hw[j].d==0){
     88             k=l=0;kk=i;ll=j;
     89             if(hw[i].d==0){
     90                 for(;i<=j;i++){
     91                     if(hw[i].can>=2)k++;
     92                     if(hw[i].can==1)l++;
     93                 }
     94                 ans+=(long long)(k+l)*(k+l-1)/2;
     95                 ans+=(long long)k*(ll-kk+1-l-k);
     96                 break;
     97             }
     98             while(1){
     99                 if(hw[i].can)k++;i++;
    100                 if(hw[i].d!=hw[i-1].d)break; 
    101             }
    102             while(1){
    103                 if(hw[j].can)l++;j--;
    104                 if(hw[j].d!=hw[j+1].d)break;
    105             }
    106             ans+=(long long)k*(ll-j-l)+l*(i-kk-k)+k*l;i--;
    107         }
    108     }
    109     if(w)map[zero]=0;
    110     return ans;
    111 }
    112 void dfs_ans(int now,int sum,int fa){
    113     hw[++tot].d=sum;
    114     hw[tot].can=map[zero+sum];
    115     map[zero+sum]++;
    116     for(int i=first[now];i;i=e[i].next)
    117         if(e[i].to!=fa&&!vis[e[i].to])
    118             dfs_ans(e[i].to,sum+e[i].d,now);
    119     map[zero+sum]--;
    120 }

    从时间复杂度和代码量上都不如标解,唉,也难怪;

  • 相关阅读:
    区块链入门
    上海美食餐厅
    《OD学hadoop》20160910某旅游网项目实战
    《OD学hadoop》20160904某旅游网项目实战
    《OD学hadoop》20160903某旅游网项目实战
    qt5-自定义类
    qt5-Qt Creator使用
    qt5-QPushButton按钮
    qt5-工程文件的介绍--快捷键
    电路分析-电阻
  • 原文地址:https://www.cnblogs.com/nietzsche-oier/p/6770122.html
Copyright © 2011-2022 走看看