• BZOJ 4326 树链剖分+二分+差分+记忆化


    去年NOIP的时候我还不会树链剖分!

    还是被UOJ 的数据卡了一组。

    差分的思想还是很神啊!

      1 #include <iostream>
      2 #include <cstring>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <ctime>
      6 #include <cstdlib>
      7 using namespace std;
      8 const int Maxn=300100;
      9 const int Inf=0x3f3f3f3f;
     10 int n,m,u,v,w,cnt,tot,MaxLen,MinLen,Minw,Maxw,Ans;
     11 int head[Maxn],dep[Maxn],siz[Maxn],father[Maxn],W[Maxn],p[Maxn],q[Maxn],dis[Maxn],Len[Maxn],c[Maxn],top[Maxn],Memory[Maxn],Root;
     12 struct Edge{int to,next,w;}edge[Maxn<<1];
     13 inline void Get_Int(int &x)
     14 {
     15     x=0;  char ch=getchar(); int f=1;
     16     while (ch<'0' || ch>'9') {if (ch=='-') f=-1; ch=getchar();}
     17     while (ch>='0' && ch<='9') {x=x*10+ch-'0'; ch=getchar();} x*=f;
     18 }
     19 inline void Put_Int(int x)
     20 {
     21     char ch[20];  int top=0;
     22     if (x==0) ch[++top]='0';
     23     while (x) ch[++top]=x%10+'0',x/=10;
     24     while (top) putchar(ch[top--]); putchar('
    ');
     25 }
     26 inline int Max(int x,int y) {return x>y?x:y;}
     27 inline int Min(int x,int y) {return x>y?y:x;}
     28 inline void Add(int u,int v,int w)
     29 {edge[cnt].to=v;edge[cnt].next=head[u];edge[cnt].w=w;head[u]=cnt++;}
     30 //==============================================
     31 void Dfs1(int u,int fa)
     32 {
     33     siz[u]=1;
     34     for (int i=head[u];i!=-1;i=edge[i].next)
     35         if (edge[i].to!=fa)
     36         {
     37             dep[edge[i].to]=dep[u]+1;
     38             father[edge[i].to]=u;
     39             dis[edge[i].to]=dis[u]+edge[i].w;
     40             W[edge[i].to]=edge[i].w;
     41             Dfs1(edge[i].to,u);
     42             siz[u]+=siz[edge[i].to];
     43         }
     44 }
     45 void Dfs2(int u,int chain,int fa)
     46 {
     47     top[u]=chain;  int k=0;
     48     for (int i=head[u];i!=-1;i=edge[i].next)
     49         if (edge[i].to!=fa && (siz[edge[i].to]>siz[k] || k==0)) k=edge[i].to;
     50     if (k==0) return;
     51     Dfs2(k,chain,u);
     52     for (int i=head[u];i!=-1;i=edge[i].next)
     53         if (edge[i].to!=fa && k!=edge[i].to) Dfs2(edge[i].to,edge[i].to,u);
     54 }
     55 inline int Lca(int u,int v)
     56 {
     57     while (true)
     58     {
     59         if (top[u]==top[v]) return dep[u]>dep[v]?v:u;
     60         if (dep[top[u]]>dep[top[v]]) u=father[top[u]]; else v=father[top[v]];
     61     }
     62 }
     63 int Get(int u,int f)
     64 {
     65     for (int i=head[u];i!=-1;i=edge[i].next)
     66         if (f!=edge[i].to)
     67             c[u]+=Get(edge[i].to,u);
     68     if (c[u]==tot) MinLen=Max(MinLen,W[u]);
     69     return c[u];
     70 }
     71 inline bool Check(int t)
     72 {
     73     MaxLen=MinLen=tot=0;
     74     memset(c,0,sizeof(c));
     75     for (int i=1;i<=m;i++)
     76         if (Len[i]>t)
     77         {
     78             c[p[i]]++,c[q[i]]++;
     79             c[Lca(p[i],q[i])]-=2;
     80             MaxLen=Max(MaxLen,Len[i]);
     81             tot++;
     82         }
     83     if (Memory[tot])
     84     {
     85         if (Memory[tot]<=t) return true;
     86         return false;
     87     }
     88     Get(Root,Root);
     89     Memory[tot]=(MaxLen-MinLen);
     90     if (Memory[tot]<=t) return true;
     91     return false;
     92 }
     93 int main()
     94 {
     95     srand(time(0));
     96     Get_Int(n),Get_Int(m);
     97     memset(head,-1,sizeof(head)); Minw=Inf;
     98     for (int i=1;i<n;i++)
     99     {
    100         Get_Int(u),Get_Int(v),Get_Int(w);
    101         Add(u,v,w),Add(v,u,w);
    102         Minw=Min(Minw,w);
    103     }
    104     for (int i=1;i<=m;i++) Get_Int(p[i]),Get_Int(q[i]);
    105     Root=rand()%n+1;
    106     father[Root]=Root; dep[Root]=1; dis[Root]=0;
    107     Dfs1(Root,Root);
    108     Dfs2(Root,Root,Root);
    109     memset(Memory,0,sizeof(Memory));
    110     for (int i=1;i<=m;i++) Len[i]=dis[p[i]]+dis[q[i]]-2*dis[Lca(p[i],q[i])],Maxw=Max(Maxw,Len[i]);
    111     int l=Minw,r=Maxw;
    112     while (l<=r)
    113     {
    114         int mid=(l+r)>>1;
    115         if (Check(mid)) Ans=mid,r=mid-1; else l=mid+1;
    116         
    117     }
    118     Put_Int(Ans);
    119     return 0;
    120 }
    C++
  • 相关阅读:
    [汇编与C语言关系]1.函数调用
    深入理解计算机系统
    设计模式
    深度探索C++对象模型
    More Effective C++
    MySQL必知必会
    数据结构与算法分析
    Java编程思想(后)
    Java编程思想(前十章)
    Java 入门
  • 原文地址:https://www.cnblogs.com/yyjxx2010xyu/p/5509639.html
Copyright © 2020-2023  润新知