Codeforces 526G Spiders Evil Plan

由于做的时候看的是中文题面,第一遍写就被卡题意了:还以为每一条都要过x,那么就是一道动态树根选择2y个叶子的奇怪题目

交完0分gg,才发现题目看错了╮(╯▽╰)╭

the node containing the candy is adjacent to at least one rope covered with a web

完全就是两道题啊。。。。。


首先考虑没有x的做法

贪心显然是对的

1.直径一定要取,否则一定可以通过把与直径最接近(以直径一段为根的lca深度最大)的一条路径改为直径来改善答案

2.剩下的一定从大取到小贪心取(在每次取完后更新每个的数据情况下),同理可证明

然后就可以通过“长链剖分”(把重链剖分里的子树大小改为最深的带权深度)解决没有x的问题了

(目测蛮好写的)

然后考虑一定要把x包含进去

然后是不会证但是感觉很对还能A的想法(⊙﹏⊙)b:

1.先把直径和前2(y-1)【因为每条路径都可以跨两条支链,但是选直径还需要一条路径】大的支链拉进答案(形成一棵树)

2.把x加入答案有两种方案:

  把离x最近的一条边切掉一半和x所在链连成一条边

  删掉最短的一条边把x所在链加入答案

 ——上图中黑色和灰色表示考虑x前做出的答案,红色表示考虑x后加上的边,灰色表示考虑x后去掉的边,左右图分别表示了两种考虑的姿势

两种方案去个比较好的,O(∩_∩)O搞定啦!


实现什么的。。。我是这么写的:

先找直径,拉出来存起来,然后把剩下的(应该是一个大森林)每个节点深度算出来(把直径上的点深度看做0)

瞎搞一波即可,没什么数据结构

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 int n,tot,lend,post,lengthd,m,N,p,q,o,x,y,lord;
  4 int fir[100001],nex[200001],dis[100001],to[200001],len[200001],d[100001],sum_d[100001],rank[100001];
  5 int fa[100001],best[100001],dep[100001],top[100001],ans[100001],sum[100001];
  6 void add(int p,int q,int o)
  7 {
  8     nex[++N]=fir[p];len[N]=o;to[N]=q;fir[p]=N;
  9 }
 10 void Dfs(int now)
 11 {
 12     for(int i=fir[now];i;i=nex[i])
 13     if(!dis[to[i]])
 14     {
 15         dis[to[i]]=dis[now]+len[i];
 16         Dfs(to[i]);
 17     }
 18 }
 19 void dfs(int now)
 20 {
 21     for(int i=1;i<=n;i++)
 22         dis[i]=0;
 23     dis[now]=1;
 24     Dfs(now);
 25 }
 26 void build(int now,int fat,int deep)
 27 {
 28     fa[now]=fat;best[now]=deep;dep[now]=deep;rank[now]=lord;
 29     for(int i=fir[now];i;i=nex[i])
 30     if(to[i]!=fat)
 31     {
 32         build(to[i],now,deep+len[i]);
 33         best[now]=max(best[now],best[to[i]]);
 34     }
 35 }
 36 void pou(int now,int Top)
 37 {
 38     bool sad=1;top[now]=Top;
 39     for(int i=fir[now];i;i=nex[i])
 40     if(to[i]!=fa[now])
 41         if(sad && best[now]==best[to[i]])
 42             sad=0,pou(to[i],Top);
 43         else
 44             pou(to[i],to[i]);
 45     if(sad)
 46         ans[++tot]=dep[now]-dep[fa[top[now]]];
 47 }
 48 void find_d()
 49 {
 50     dfs(1);int start=0,bes=0,end=0;
 51     for(int i=1;i<=n;i++)
 52         if(dis[i]>bes) bes=dis[i],start=i;
 53     dfs(start);bes=0;
 54     for(int i=1;i<=n;i++)
 55         if(dis[i]>bes) bes=dis[i],end=i;
 56     for(d[lend=1]=post=end;post!=start;d[++lend]=post,rank[post]=lend)
 57         for(int i=fir[post];i;i=nex[i])
 58             if(dis[to[i]]<dis[post])
 59             {
 60                 post=to[i];
 61                 break;
 62             }
 63     lengthd=dis[end]-1;
 64     for(int i=2;i<=lend;i++)
 65         sum_d[i]=dis[d[i]]-1;
 66 }
 67 int main()
 68 {
 69     scanf("%d%d",&n,&m);
 70     for(int i=1;i<n;i++)
 71         scanf("%d%d%d",&p,&q,&o),
 72         add(p,q,o),add(q,p,o);
 73     find_d();
 74     for(int i=1;i<=lend;i++)
 75         for(int j=fir[d[i]];j;j=nex[j])
 76         {
 77             if(i>1 && to[j]==d[i-1]) continue;
 78             if(i<lend && to[j]==d[i+1]) continue;
 79             lord=i;
 80             build(to[j],d[i],len[j]);
 81             pou(to[j],to[j]);
 82         }
 83     sort(ans+1,ans+tot+1,greater<int>());
 84     for(int i=1;i<=tot;i++)
 85         sum[i]=sum[i-1]+ans[i];
 86     int lastans=0;
 87     if(0)
 88     {
 89         for(int i=1;i<=lend;i++)
 90             printf("%d ",d[i]);
 91         puts("");
 92     } 
 93     for(int i=1;i<=m;i++)
 94     {
 95         scanf("%d%d",&x,&y);
 96         if(x==7 && y==2)
 97             int e=1;
 98         x=(x+lastans-1)%n+1;y=(y+lastans-1)%n+1;
 99         y=y*2-2;
100         if(y>=tot)
101         {
102             lastans=sum[tot]+lengthd;
103             printf("%d
",lastans);
104         }
105         else
106         if(!y)
107             if(!dep[x])
108             {
109                 lastans=lengthd;
110                 printf("%d
",lastans);
111             }
112             else
113             {
114                 lastans=best[x]+max(sum_d[rank[x]],lengthd-sum_d[rank[x]]);
115                 printf("%d
",lastans);
116             }
117         else
118         if(dep[x] && best[x]-dep[fa[top[x]]]<ans[y])
119         {
120             lastans=lengthd+sum[y-1];
121             int enter=x;
122             while(dep[enter] && best[enter]-dep[fa[top[enter]]]<ans[y])
123                 enter=fa[top[enter]];
124             if(dep[enter])
125                 lastans+=max(best[x]-dep[enter],best[x]-best[enter]+ans[y]);
126             else
127             {
128                 lastans+=best[x];
129                 if(ans[y]>min(sum_d[rank[x]],lengthd-sum_d[rank[x]]))
130                     lastans+=ans[y]-min(sum_d[rank[x]],lengthd-sum_d[rank[x]]);
131             }
132             printf("%d
",lastans);
133         }
134         else
135         {
136             lastans=sum[y]+lengthd;
137             printf("%d
",sum[y]+lengthd);
138         }
139     }
140     return 0;
141 }

写的又臭又长╮(╯▽╰)╭

原文地址:https://www.cnblogs.com/wanglichao/p/6480629.html