AGC029 E: Wandering TKHS
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相关推荐
- AtCoder AGC029E Wandering TKHS
题目链接 https://atcoder.jp/contests/agc029/tasks/agc029_e 题解 写了一半发现假了然后强行乱改一通改对了-- 我们用"\(u\)子树内小于\ ...
- 【学习笔记】AGC009/AGC019/AGC029/AGC035
AGC009 Eternal Average 奥妙重重 如果我们用树的结构来描述操作,设一个点的深度为xix_ixi,那么一定满足∑k−xi=1\sum k^{-x_i}=1∑k−xi=1,并且 ...
- HDU 6229 Wandering Robots 找规律+离散化
题目链接:Wandering Robots 题解:先讲一下规律,对于每一个格子它可以从多少个地方来有一个值(可以从自己到自己),然后答案就是统计合法格子上的数与所有格子的数的比值 比如说样例的3 0格 ...
- AtCoder题解 —— AtCoder Beginner Contest 182 —— D - Wandering
题目相关 题目链接 AtCoder Beginner Contest 182 D 题,https://atcoder.jp/contests/abc182/tasks/abc182_d. Proble ...
- ACM-ICPC 2019 山东省省赛 C Wandering Robot
这个题额,我觉的是一道水题,思维题,需要考虑的情况比较多,题意一个机器人给一条指令,循环n遍,问此过程中离原点最远距离. 考虑最远距离可能出现的的情况. 每次循环之后距离至少为0: 1.假设他每一次循 ...
- 流利阅读day4 the Wandering Earth
science fiction 科幻 sci-fi blockbuster:sth very succesful (especially a film or a book) amid,mid,amid ...
- 微软todo使用教程_Todo教程可能很有趣-但是,这是从头开始构建自己的项目的方法...
微软todo使用教程 There are many great tutorials that walk you through creating apps, from simple todo list ...
- 2017 ACM ICPC Asia Shenyang Regional Contest 题解(10 / 13)【每日亿题2 / 16】
整理的算法模板合集: ACM模板 点我看算法全家桶系列!!! 实际上是一个全新的精炼模板整合计划 目录 A.(2017 ICPC shenyang I)Little Boxes B.(2017 ICP ...
- rsync单项同步文件
我主要用rysnc同步文件,rsync是一款非常优秀的文件同步管理软件,它也支持多种操作系统平台,在Unix环境中,rsync有着卓绝的功绩.希望这篇文档能对一些朋友有所帮助. 1. Install ...
最新文章
- 专访高磊:安卓APK安全加固的引领者
- 用存储过程创建的分页
- 配置CentOS的网络环境
- UNIX再学习 -- 死磕内存管理
- window.Event参数详解
- 2018年不能错过的 14 个 Java 库
- 2013_chengdu_onsite
- linux下drcom无法上网,drcom为什么还是不能上网啊!
- elasticjob 分片策略
- Node.js 沙箱易受原型污染攻击
- DateTimePicker 控件置空
- 成功的人不是最聪明的那个人,但绝对是一个交流很棒的人
- 快速清洗数据库数据(数据脱敏方案)
- 各国语言缩写-各国语言简称,世界各国域名缩写
- Pycharm Debug调试(纯干货)
- 苹果奖学金获得者:我的自学 iOS 开发历程
- 7-97 约会成功了吗?
- Android面试基础之BroadcastReceiver详解(斗帝养成系列四)
- 个人学习(解决)练习ssm框架遇到的问题No qualifying bean of type ‘service.BookTypeService‘ available:
- Workflow 在数据仓库建设中的应用与优化