zoukankan      html  css  js  c++  java
  • LGP2680

    7.15号,一天的时间耗在这个题上,ennn,反思总结.

    1.玄学编译错误:一定要注意结构体的空间大小.

    2.关于求树任意两点距离:用dis数组记录根节点到每一点距离,对于from,to

    两点,用dis[from]+dis[to]-2*dis[LCA]即可求得树上两点距离,o(m)遍历便可,

    今天用最短路dj求树上两点,o((n+m)*log(m))则不值.

    3.板子一定要打稳,LCA今天调了很多次.

    4.get求线段并的差分方法.

    1.暴力

    显然我们可以想到暴力枚举边权为零,再算出对m个计划的影响,求m个计划的最大时间中的最小值

    要注意dis数组的使用,不要sb地用最短路,树上路线唯一确定.

    2.正解.

    1.对于最大值最小问题,我们会想到二分答案.将ans定义为能询问路径中合法存在的最长路径,我

    们的任务就是将ans不断缩小.将询问路径中长度比ans大的找出来.可以这样理解,maxdis是我们

    期望的最长最小,对那些比它长的路径我们希望通过虫洞减少,只有长的才对'最长路径'有影响.所以

    我们找出最长的长出maxdis多长,看能不能通过虫洞消除,若能消除则一定有合法的更小值.若不能

    则只能maxdis变长,对用虫洞去消长度的要求小一点.

    2.如何用虫洞消?一定消比它长度的路径的交集路径的最大值.因为一定要影响整体,整体一个不合

    法,maxdis就一定扩大,这就是为什么用最长的减最maxdis,因为我希望都合法,maxdis才缩小

    3.如何去路径并?先考虑线段并,暴力染色看染色次数?线段树O(logn)维护?其实可以用差分.将线段

    的l设置为1,r的后一位为-1,求一遍前缀和的过程中能得到每个点被覆盖次数.可理解为在线段区间

    我们用1体现线段区间(区间两字用前缀和体现)染色,-1则体现消除影响(因为脱离区间).那么树上的

    两点的距离可看做两点到LCA的两条线段,(num[LCA]-=2即这个意思).当覆盖次数等于加入线段个

    数即表示它被所有区间覆盖,我们要求的虫洞即在这.

      1 #include<iostream>
      2 #include<cstring>
      3 #include<cstdio>
      4 using namespace std;
      5 #define e exit(0)
      6 #define R register
      7 #define ll long long
      8 const int maxn=3*1e6+10;
      9 long long n,m,cnt,l,r,deep,dfn[maxn],num[maxn],h[maxn],fa[maxn],dis[maxn],head[maxn],bz[maxn][24];
     10 struct bian{
     11     ll to,next,v;
     12 }len[maxn<<1];
     13 struct kkk{
     14     ll from,to,lcaa,diss;
     15 }ask[maxn<<1];
     16 inline long long fd()
     17 {
     18     long long s=1,t=0;
     19     char c=getchar();
     20     while(c<'0'||c>'9')
     21     {
     22         if(c=='-')
     23             s=-1;
     24         c=getchar();
     25     }
     26     while(c>='0'&&c<='9')
     27     {
     28         t=t*10+c-'0';
     29         c=getchar();
     30     }
     31     return s*t;
     32 }
     33 void add(ll from,ll to,ll v)
     34 {
     35     len[++cnt].v=v;
     36     len[cnt].to=to;
     37     len[cnt].next=head[from];
     38     head[from]=cnt;
     39 }
     40 void dfs(ll x)
     41 {
     42     dfn[++deep]=x;
     43     for(R ll k=head[x];k;k=len[k].next)
     44     {
     45         ll to=len[k].to;
     46         if(!h[to])
     47         {
     48             h[to]=h[x]+1;
     49             fa[to]=x;
     50             dfs(to);
     51         }
     52     }
     53 }
     54 void makebz()
     55 {
     56     h[1]=1,fa[1]=1;
     57     dfs(1);
     58     for(R ll i=1;i<=n;++i)
     59         bz[i][0]=fa[i];
     60     for(R ll j=1;j<=19;++j)
     61         for(R ll i=1;i<=n;++i)
     62             bz[i][j]=bz[bz[i][j-1]][j-1];    
     63 }
     64 long long LCA(ll x,ll y)
     65 {
     66     if(h[x]<=h[y])
     67         swap(x,y);
     68     for(R ll k=19;k>=0;--k)
     69         if(h[bz[x][k]]>=h[y])
     70             x=bz[x][k];
     71     if(x==y)
     72         return x;
     73     for(R ll k=19;k>=0;--k)
     74         if(bz[x][k]!=bz[y][k])
     75             x=bz[x][k],y=bz[y][k];
     76     return fa[x];
     77 }
     78 void dfsdis(ll x,ll sum,ll fa)
     79 {
     80     for(R ll k=head[x];k;k=len[k].next)
     81     {
     82         ll to=len[k].to,v=len[k].v;
     83         if(to==fa) continue;
     84         ll nowsum=sum+v;
     85         dis[to]=nowsum;
     86         dfsdis(to,nowsum,x);
     87     }
     88 }
     89 bool check(ll mid)
     90 {
     91     ll cnt=0,maxdis=0;
     92     memset(num,0,sizeof(num));
     93     for(R ll i=1;i<=m;++i)
     94     {
     95         if(ask[i].diss>mid)
     96         {
     97             ll from=ask[i].from,to=ask[i].to,lca=ask[i].lcaa;
     98             ++num[from],++num[to],num[lca]-=2;
     99             maxdis=max(maxdis,ask[i].diss-mid);
    100             ++cnt;
    101         }
    102     }
    103     if(cnt==0)
    104         return true;
    105     for(R ll i=n;i>=1;--i)
    106         num[fa[dfn[i]]]+=num[dfn[i]];
    107     for(R ll i=2;i<=n;++i)
    108         if(num[i]==cnt&&dis[i]-dis[fa[i]]>=maxdis)
    109             return true;
    110     return false;
    111 }
    112 int main()
    113 {
    114 //    freopen("s.in","r",stdin);
    115 //    freopen("s.out","w",stdout);
    116     n=fd(),m=fd();
    117     for(R ll i=1;i<n;++i)
    118     {
    119         ll from=fd(),to=fd(),v=fd();
    120         add(from,to,v),add(to,from,v);
    121         r+=v;
    122     }
    123     makebz();
    124     dfsdis(1,0,1);
    125     for(R ll i=1;i<=m;++i)
    126     {
    127         ll from=fd(),to=fd();
    128         ask[i].from=from,ask[i].to=to;
    129         ask[i].lcaa=LCA(from,to),ask[i].diss=dis[from]+dis[to]-2*dis[ask[i].lcaa];
    130     }
    131     while(l<r)
    132     {
    133         ll mid=(l+r)>>1;
    134         if(check(mid)) r=mid;
    135         else l=mid+1;
    136     }
    137     printf("%lld",l);
    138     return 0;
    139 }

     

  • 相关阅读:
    jmeter之三种参数化
    linux(centos6.5)常用命令
    win10+jdk+mysql+tomcat+jpress环境搭建与部署
    [剑指Offer] 29.最小的K个数
    [C/C++] C++中new的语法规则
    [C/C++] 深拷贝和浅拷贝
    [C/C++] #ifdef和#endif
    [C/C++] C++声明和定义的区别
    [C/C++] extern关键字详解以及与static、const区别
    [C/C++] static在C和C++中的用法和区别
  • 原文地址:https://www.cnblogs.com/xqysckt/p/11194953.html
Copyright © 2011-2022 走看看