• [CF526G]Spiders Evil Plan


    题意

    https://codeforces.com/problemset/problem/526/G


    思考

    先考虑只有一次询问。如果我们选择了k条路径,那么就会有2k个叶子节点;反过来,如果选择了2k个叶子节点,总存在一种方案使得组成的k条路径形成一个联通块。因为若还没有连通块,总可以交换两条不交叉路径的端点,使他们交叉。

    这样问题转化为:选k个从根节点(当让是询问的x为根)到叶子节点的路径,最大化经过的边权之和。这是一个经典的问题,可以按照长链剖分的思想,用堆来解决。

    值得注意的是,第一次选择一定会到达树的直径的某个端点上。因此我们任选直径的某一个端点,让它作为树根。

    预处理出所有k=1~n的答案。对于询问(u,k),若u已经在k答案的路径上了,直接输出;否则分三种情况考虑:

    1.直径换一个端点,即在k答案的基础上塞进u子树中深度最大的叶子节点。作为补偿,找到u在k-1答案中第一次被选中的祖宗,减去两倍它的深度。

    2.在k-1答案的基础上塞进u子树中深度最大的叶子节点。作为补偿,找到u在k-1答案中第一次被选中的祖宗,减去它的深度。

    3.在k-1答案的基础上换一个儿子。

    时间复杂度$O(nlogn)$


    代码

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 const int maxn=1E5+5;
      4 int n,m;
      5 int size,head[maxn*2];
      6 int lastans,root,now,dep[maxn],ans[maxn],son[maxn],fa[maxn][20],maxdep[maxn];
      7 int tot,vis[maxn];
      8 struct edge
      9 {
     10     int to,next,w;
     11 }E[maxn*2];
     12 struct node
     13 {
     14     int u,val;
     15     node(int a=0,int b=0)
     16     {
     17         u=a,val=b;
     18     }
     19     bool operator<(const node&A)const
     20     {
     21         return val<A.val; 
     22     }
     23 };
     24 priority_queue<node>Q; 
     25 inline void add(int u,int v,int w)
     26 {
     27     E[++size].to=v;
     28     E[size].next=head[u];
     29     E[size].w=w;
     30     head[u]=size;
     31 }
     32 void dfs(int u,int F,int d)
     33 {
     34     maxdep[u]=dep[u]=d;
     35     son[u]=u;
     36     if(d>now)
     37         root=u,now=d;
     38     for(int i=head[u];i;i=E[i].next)
     39     {
     40         int v=E[i].to;
     41         if(v==F)
     42             continue;
     43         dfs(v,u,d+E[i].w);
     44         if(maxdep[v]>maxdep[u])
     45             maxdep[u]=maxdep[v],son[u]=son[v];
     46     }
     47 }
     48 void initson(int u,int F,int d)
     49 {
     50     maxdep[u]=dep[u]=d;
     51     son[u]=u;
     52     for(int i=head[u];i;i=E[i].next)
     53     {
     54         int v=E[i].to;
     55         if(v==F)
     56             continue;
     57         initson(v,u,d+E[i].w);
     58         if(maxdep[v]>maxdep[u])
     59             maxdep[u]=maxdep[v],son[u]=v;
     60     }
     61 }
     62 void get(int u,int F,int d)
     63 {
     64     if(son[u]==u)
     65         Q.push(node(u,d));
     66     fa[u][0]=F;
     67     for(int i=1;i<20;++i)
     68         fa[u][i]=fa[fa[u][i-1]][i-1];
     69     for(int i=head[u];i;i=E[i].next)
     70     {
     71         int v=E[i].to;
     72         if(v==F)
     73             continue;
     74         else if(v==son[u])
     75             get(v,u,d+E[i].w);
     76         else
     77             get(v,u,E[i].w);
     78     }
     79 }
     80 void init()
     81 {
     82     initson(root,root,0);
     83     get(root,root,0);
     84     while(!Q.empty())
     85     {
     86         node A=Q.top();
     87         Q.pop();
     88         ++tot;
     89         ans[tot]=ans[tot-1]+A.val;
     90         for(int u=A.u;!vis[u];u=fa[u][0])
     91             vis[u]=tot;
     92     }
     93 }
     94 inline int solve(int u,int k)
     95 {
     96     k=min(k,tot);
     97     if(vis[u]<=k)
     98         return ans[k];
     99     int F=u;
    100     for(int i=19;i>=0;--i)
    101         if(vis[fa[F][i]]>k)
    102             F=fa[F][i];
    103     F=fa[F][0];
    104     return max(ans[k]+maxdep[u]-2*dep[F],max(
    105                maxdep[u]-dep[F]+ans[k-1],
    106                ans[k]+maxdep[u]-maxdep[F]));
    107 } 
    108 int main()
    109 {
    110     ios::sync_with_stdio(false);
    111     cin>>n>>m;
    112     for(int i=2;i<=n;++i)
    113     {
    114         int x,y,z;
    115         cin>>x>>y>>z;
    116         add(x,y,z);
    117         add(y,x,z);
    118     }
    119     dfs(1,1,0);
    120     now=0;
    121     dfs(root,root,now);
    122     init();
    123     while(m--)
    124     {
    125         int x,y;
    126         cin>>x>>y;
    127         x=(x+lastans-1)%n+1;
    128         y=(y+lastans-1)%n+1;
    129         lastans=solve(x,y*2-1);
    130         cout<<lastans<<endl;
    131     }
    132     return 0;
    133 }
    View Code
  • 相关阅读:
    eclipse注释乱码的一个小问题
    《java 编程思想》 读书笔记 (一)
    《java 编程思想》 读书笔记 (一)
    055_SSM——sprinMVC的返回值
    054_jQuary——html()与text()方法的区别?
    053_Servlet——resp.getWrite()与resp.getPrint()的区别?
    052_html——html转环成jsp出现乱码的问题?
    051_html——checkbox的默认值与工作属性
    050_SSM——SpringMVCV中的各个器都起了什么作用?
    047_SSM——为什么返回String使用StringHttpMessageConverter解析时会造成乱码?
  • 原文地址:https://www.cnblogs.com/GreenDuck/p/11416407.html
Copyright © 2020-2023  润新知