首页 > 代码库 > Codeforces 526G Spiders Evil Plan
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\n",lastans); 104 } 105 else 106 if(!y) 107 if(!dep[x]) 108 { 109 lastans=lengthd; 110 printf("%d\n",lastans); 111 } 112 else 113 { 114 lastans=best[x]+max(sum_d[rank[x]],lengthd-sum_d[rank[x]]); 115 printf("%d\n",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\n",lastans); 133 } 134 else 135 { 136 lastans=sum[y]+lengthd; 137 printf("%d\n",sum[y]+lengthd); 138 } 139 } 140 return 0; 141 }
写的又臭又长╮(╯▽╰)╭
Codeforces 526G Spiders Evil Plan