E: Wandering TKHS - AtCoder Grand Contest 029 | AtCoder

分类讨论好题(也不太算分类讨论)

方法:感受过程手玩,考虑能不能提前预算一些东西,或者递推,递归

也就是,找问题划分点

关注一个点x到根节点的最大值mx[x](包括自己)

因为最大值的父亲fa[mx[x]]的ans一定不会扩展mx[x]

所以求出mx[x]

对于mx[x]!=x情况

定义son[x],x的mx[x]往x方向走的第一个儿子

x一定会历经艰难扩展到mx,期间son[x]子树内,mx[*]=mx[x]的*都会被扩展。第一部分

走到了mx

之后,son[x]子树不会有任何扩展,

但是还可能会扩展一些mx除了son[x]的其他子树点y

如果y到根的次大值(最大值一定也是mx)是mx到根的次大值se[mx]的话,那么一定在次大值及之前会被扩展。第二部分

所以,次大值也关心。

然后就是ans[fa[mx]]了,之前已经算过,而且不会算重!第三部分

子树某个值出现次数

第一部分线段树合并

第二部分线段树合并,再减去son[x]子树的贡献

对于mx[x]==x情况

更好处理

直接变成上述情况的第二部分。mx子树内,se[*]=se[x]的个数

线段树合并。

代码:

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=998244353;
int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
void inc(int &x,int y){x=ad(x,y);}
int mul(int x,int y){return (ll)x*y%mod;}
void inc2(int &x,int y){x=mul(x,y);}
int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
}
//using namespace Modulo;
namespace Miracle{
const int N=2e5+5;
int n;
struct node{int nxt,to;
}e[2*N];
int hd[N],cnt;
void add(int x,int y){e[++cnt].nxt=hd[x];e[cnt].to=y;hd[x]=cnt;
}
int se[N],mx[N];
int son[N];
int pa[N];
void dfs(int x,int fa){se[x]=se[fa];mx[x]=mx[fa];if(x>mx[x]){se[x]=mx[x];mx[x]=x;}else se[x]=max(se[x],x);if(mx[x]==mx[fa]){if(mx[fa]==fa) son[x]=x;else son[x]=son[fa];}for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(y==fa) continue;pa[y]=x;dfs(y,x);}
}
struct tr{int ls,rs;int cnt[2];
}t[N*60];
int tot;
int rt[N];
#define mid ((l+r)>>1)
void upda(int &x,int l,int r,int p,int c){if(!x) x=++tot;if(l==r){t[x].cnt[c]++;return;}if(p<=mid) upda(t[x].ls,l,mid,p,c);else upda(t[x].rs,mid+1,r,p,c);
}
int merge(int x,int y,int l,int r){if(!x||!y) return x+y;if(l==r){t[x].cnt[0]=t[x].cnt[0]+t[y].cnt[0];t[x].cnt[1]=t[x].cnt[1]+t[y].cnt[1];return x;}t[x].ls=merge(t[x].ls,t[y].ls,l,mid);t[x].rs=merge(t[x].rs,t[y].rs,mid+1,r);return x;
}
void dfs2(int x,int fa){upda(rt[x],1,n,mx[x],1);upda(rt[x],1,n,se[x],0);for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(y==fa) continue;dfs2(y,x);rt[x]=merge(rt[x],rt[y],1,n);}
}
int query(int x,int l,int r,int p,int c){if(!x) return 0;if(l==r) return t[x].cnt[c];if(p<=mid) return query(t[x].ls,l,mid,p,c);else return query(t[x].rs,mid+1,r,p,c);
}
int ans[N];
void fin(int x,int fa){if(x!=1){if(mx[x]!=x){int A=query(rt[son[x]],1,n,mx[x],1),B=query(rt[mx[x]],1,n,se[mx[x]],0),C=-query(rt[son[x]],1,n,se[mx[x]],0),D=ans[pa[mx[x]]];// cout<<" xx "<<x<<" : "<<A<<" "<<B<<" "<<C<<" "<<D<<endl;ans[x]=A+B+C+D;}else{ans[x]=query(rt[x],1,n,se[x],0)+ans[fa];}}for(reg i=hd[x];i;i=e[i].nxt){int y=e[i].to;if(y==fa) continue;fin(y,x);}
}
int main(){rd(n);int x,y;for(reg i=1;i<n;++i){rd(x);rd(y);add(x,y);add(y,x);}dfs(1,0);dfs2(1,0);// prt(se,1,n);// prt(mx,1,n);// prt(son,1,n);fin(1,0);prt(ans,2,n);return 0;
}}
signed main(){Miracle::main();return 0;
}/*Author: *Miracle*
*/

mx的发现很关键,以mx位置为划分点,可以把问题分成若干部分处理,

由于fa[mx]不会再进入mx,还支持递归!

转载于:https://www.cnblogs.com/Miracevin/p/10975883.html

AGC029 E: Wandering TKHS相关推荐

  1. AtCoder AGC029E Wandering TKHS

    题目链接 https://atcoder.jp/contests/agc029/tasks/agc029_e 题解 写了一半发现假了然后强行乱改一通改对了-- 我们用"\(u\)子树内小于\ ...

  2. 【学习笔记】AGC009/AGC019/AGC029/AGC035

    AGC009 Eternal Average 奥妙重重 如果我们用树的结构来描述操作,设一个点的深度为xix_ixi​,那么一定满足∑k−xi=1\sum k^{-x_i}=1∑k−xi​=1,并且 ...

  3. HDU 6229 Wandering Robots 找规律+离散化

    题目链接:Wandering Robots 题解:先讲一下规律,对于每一个格子它可以从多少个地方来有一个值(可以从自己到自己),然后答案就是统计合法格子上的数与所有格子的数的比值 比如说样例的3 0格 ...

  4. AtCoder题解 —— AtCoder Beginner Contest 182 —— D - Wandering

    题目相关 题目链接 AtCoder Beginner Contest 182 D 题,https://atcoder.jp/contests/abc182/tasks/abc182_d. Proble ...

  5. ACM-ICPC 2019 山东省省赛 C Wandering Robot

    这个题额,我觉的是一道水题,思维题,需要考虑的情况比较多,题意一个机器人给一条指令,循环n遍,问此过程中离原点最远距离. 考虑最远距离可能出现的的情况. 每次循环之后距离至少为0: 1.假设他每一次循 ...

  6. 流利阅读day4 the Wandering Earth

    science fiction 科幻 sci-fi blockbuster:sth very succesful (especially a film or a book) amid,mid,amid ...

  7. 微软todo使用教程_Todo教程可能很有趣-但是,这是从头开始构建自己的项目的方法...

    微软todo使用教程 There are many great tutorials that walk you through creating apps, from simple todo list ...

  8. 2017 ACM ICPC Asia Shenyang Regional Contest 题解(10 / 13)【每日亿题2 / 16】

    整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2017 ICPC shenyang I)Little Boxes B.(2017 ICP ...

  9. rsync单项同步文件

    我主要用rysnc同步文件,rsync是一款非常优秀的文件同步管理软件,它也支持多种操作系统平台,在Unix环境中,rsync有着卓绝的功绩.希望这篇文档能对一些朋友有所帮助. 1. Install ...

最新文章

  1. 专访高磊:安卓APK安全加固的引领者
  2. 用存储过程创建的分页
  3. 配置CentOS的网络环境
  4. UNIX再学习 -- 死磕内存管理
  5. window.Event参数详解
  6. 2018年不能错过的 14 个 Java 库
  7. 2013_chengdu_onsite
  8. linux下drcom无法上网,drcom为什么还是不能上网啊!
  9. elasticjob 分片策略
  10. Node.js 沙箱易受原型污染攻击
  11. DateTimePicker 控件置空
  12. 成功的人不是最聪明的那个人,但绝对是一个交流很棒的人
  13. 快速清洗数据库数据(数据脱敏方案)
  14. 各国语言缩写-各国语言简称,世界各国域名缩写
  15. Pycharm Debug调试(纯干货)
  16. 苹果奖学金获得者:我的自学 iOS 开发历程
  17. 7-97 约会成功了吗?
  18. Android面试基础之BroadcastReceiver详解(斗帝养成系列四)
  19. 个人学习(解决)练习ssm框架遇到的问题No qualifying bean of type ‘service.BookTypeService‘ available:
  20. Workflow 在数据仓库建设中的应用与优化

热门文章

  1. 利用numpy对已知样本点进行多项式拟合
  2. 智能如何产生,这仍然是个问题
  3. FrostSulliven最新发布引领全球增长的60大技术
  4. 边缘计算有哪些关键技术?
  5. 什么是边缘计算(Edge AI)?
  6. 产业|世界十大工业自动化公司,你知道几家?
  7. 从技术角度探讨:深度传感器行业有哪些发展机会
  8. 日本面向未来的特定科技领域技术预见分析
  9. 机器学习虽好,也要看什么场合!
  10. 图解谷歌大脑丶城市大脑丶全球脑与互联网大脑的关系