Codechef August Challenge 2019 Chef and Gordon Ramsay
[传送门]
题目即求所有的三元组,相对大小关系同 $p_1,p_2,p_3$。
题解说都很清楚,这里写一下过程整理一下思路。
如果我们枚举中间这个元素,那么就是统计子树内外有多少个大于这个数和小于这个数的个数。
假设$a_1$,$a_3$的$LCA$不是$a_2$,那么就是一个在$a_2$子树内一个在子树外。
设$S_u$, $B_u$分别为$u$子树内小于$u$和大于$u$的节点个数,$S_t$, $B_t$分别为整棵树小于$u$和大于$u$的节点个数。
当$p_2 = 1$时,对答案的贡献为$B_u \times (B_t - B_u)$
当$p_2 = 2$时,对答案的贡献为$B_u \times (S_t - S_u) + S_u \times (B_t - B_u)$
当$p_2 = 1$时,对答案的贡献为$S_u \times (S_t - S_u)$
当$a_1$和$a_3$的$LCA$是$a_2$时,枚举$u$的子节点。
设$S_v$为$u$的子节点$v$的子树中,小于$u$的节点个数,$B_v$为$u$的子节点$v$的子树中,大于$u$的节点个数。
当$p_2 = 1$时,对答案的贡献为$B_v \times (B_u - B_v)$
当$p_2 = 2$时,对答案的贡献为$S_v \times (B_u - B_v) + B_v \times (S_u - S_v)$
当$p_2 = 1$时,对答案的贡献为$S_v \times (S_u - S_v)$
这部分的贡献会被算两次,所以最后得除以二。
查子树内都多少节点大于/小于该节点的,题解用了dfs序+树状数组,但是对于第二部分求答案很麻烦。所以我用了线段树合并,不过会卡常,那么只求一遍小于的,再用子树的size减去这个值就得到大于的。
#include <bits/stdc++.h>
#define pii pair<int, int>
#define ll long long
using namespace std; namespace IO {
const int MAXSIZE = << ;
char buf[MAXSIZE], *p1, *p2;
#define gc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, MAXSIZE, stdin), p1 == p2) ? EOF : *p1++)
template<class T>
inline void read(T &x) {
x = ; T f = ; char c = gc();
while (!isdigit(c)) { if (c == '-') f = -; c = gc(); }
while (isdigit(c)) x = x * + (c ^ ), c = gc();
x *= f;
}
char pbuf[ << ], *pp = pbuf;
inline void push(const char &c) {
if (pp - pbuf == << ) fwrite(pbuf, , << , stdout), pp = pbuf;
*pp++ = c;
}
inline void write(int x) {
static int sta[];
int top = ;
do {
sta[top++] = x % , x /= ;
} while (x);
while (top) push(sta[--top] + '');
}
} using namespace IO; const int N = 1e5 + ; int root[N], p[], n, sz[N];
vector<int> G[N]; struct Seg {
struct Tree {
int lp, rp, sum;
} tree[N * ];
int tol;
inline void clear() {
tol = ;
memset(tree, , sizeof(tree));
}
inline void pushup(int p) {
tree[p].sum = tree[tree[p].lp].sum + tree[tree[p].rp].sum;
}
void update(int &p, int l, int r, int pos) {
if (!p) p = ++tol;
if (l == r) {
tree[p].sum++;
return;
}
int mid = l + r >> ;
if (pos <= mid) update(tree[p].lp, l, mid, pos);
else update(tree[p].rp, mid + , r, pos);
pushup(p);
}
int merge(int p, int q, int l, int r) {
if (!p || !q) return p | q;
int u = ++tol;
int mid = l + r >> ;
tree[u].lp = merge(tree[p].lp, tree[q].lp, l, mid);
tree[u].rp = merge(tree[p].rp, tree[q].rp, mid + , r);
pushup(u);
return u;
}
int query(int p, int l, int r, int x, int y) {
if (x > y) return ;
if (!p) return ;
if (x <= l && y >= r) return tree[p].sum;
int mid = l + r >> ;
int ans = ;
if (x <= mid) ans += query(tree[p].lp, l, mid, x, y);
if (y > mid) ans += query(tree[p].rp, mid + , r, x, y);
return ans;
}
} seg; ll ans; inline void init() {
ans = ;
seg.clear();
for (int i = ; i <= n; i++) G[i].clear(), root[i] = ;
} void dfs(int u, int fa) {
seg.update(root[u], , n, u);
vector<pii> vec;
int su = , bu = ;
int st = u - , bt = n - u;
sz[u] = ;
for (auto v: G[u]) {
if (v == fa) continue;
dfs(v, u);
sz[u] += sz[v];
int sv = seg.query(root[v], , n, , u - ), bv = sz[v] - sv;
su += sv, bu += bv;
vec.push_back(pii(sv, bv));
root[u] = seg.merge(root[u], root[v], , n);
}
if (p[] == )
ans += 1LL * bu * (bt - bu);
else if (p[] == )
ans += 1LL * bu * (st - su) + 1LL * su * (bt - bu);
else
ans += 1LL * su * (st - su);
ll res = ;
for (auto pp: vec) {
if (p[] == )
res += 1LL * pp.second * (bu - pp.second);
else if (p[] == )
res += 1LL * pp.first * (bu - pp.second) + 1LL * pp.second * (su - pp.first);
else
res += 1LL * pp.first * (su - pp.first);
}
ans += res / ;
} int main() {
// freopen("in.txt", "r", stdin);
int T;
read(T);
while (T--) {
read(n);
init();
for (int i = ; i < ; i++) read(p[i]);
for (int i = ; i < n; i++) {
int u, v;
read(u), read(v);
G[u].push_back(v);
G[v].push_back(u);
}
dfs(, );
printf("%lld\n", ans);
}
return ;
}
Codechef August Challenge 2019 Chef and Gordon Ramsay的更多相关文章
- Codechef August Challenge 2019 Division 2
Preface 老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2 因为台风的原因challenge并没有写,所以水了个Rank7 A Football SB模拟题不解释 #include< ...
- Codechef August Challenge 2018 : Chef at the River
传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...
- 【CodeChef】August Challenge 2019 Div2 解题报告
点此进入比赛 \(T1\):Football(点此看题面) 大致题意: 求\(max(20a_i-10b_i,0)\). 送分题不解释. #include<bits/stdc++.h> # ...
- Codechef April Challenge 2019 游记
Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...
- CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And Easy Xor Queries
https://www.codechef.com/DEC17/problems/CHEFEXQ 题意: 位置i的数改为k 询问区间[1,i]内有多少个前缀的异或和为k 分块 sum[i][j] 表示第 ...
- CF&&CC百套计划2 CodeChef December Challenge 2017 Chef and Hamming Distance of arrays
https://www.codechef.com/DEC17/problems/CHEFHAM #include<cstdio> #include<cstring> #incl ...
- CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And his Cake
https://www.codechef.com/DEC17/problems/GIT01 #include<cstdio> #include<algorithm> using ...
- CodeChef April Challenge 2019题解
传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...
- Codechef October Challenge 2019 Division 1
Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...
随机推荐
- How to sort HashSet in Java
How to sort HashSet in Java 方法一:By Converting HashSet to List 方法二:By Converting HashSet to TreeSet i ...
- Spring JPA事务
目录 1. 概述 促进阅读: 2. 配置不带XML的事务 3. 使用XML配置事务 4. @Transactional 注解 5. 潜在的陷阱 5.1. 事务和代理 5.2. 更改隔离级别 5.3. ...
- R语言dataframe的常用操作总结
前言:近段时间学习R语言用到最多的数据格式就是data.frame,现对data.frame常用操作进行总结,其中函数大部分来自dplyr包,该包由Hadley Wickham所作,主要用于数据的清洗 ...
- 【学习笔记】Docker基础
基本概念 Docker是什么? Docker是一种基于Golang开发的虚拟化技术,开发人员和系统管理员使用容器开发,部署和运行应用程序的平台. 使用Linux容器部署应用程序称为容器化. 容器不是新 ...
- Linux学习笔记之秋水BBR一键部署
0x00 本脚本适用环境 系统支持:CentOS 6+,Debian 7+,Ubuntu 12+内存要求:≥128M 阅读文章时请除手动删出干扰字符“1”.(Shadowsocks) 0x01 关于本 ...
- SpringBoot中使用@scheduled定时执行任务需要注意的坑
spring boot: 计划任务@ EnableScheduling和@Scheduled @Scheduled中的参数说明 @Scheduled(fixedRate=2000):上一次开始执行时间 ...
- SQL Server中COALESCE函数的用法
在SQL Server中COALESCE函数,会返回其参数中第一个不为NULL的参数,效果如下: SELECT COALESCE(NULL,NULL,N'A',NULL,NULL) 结果: SELEC ...
- SQL Server的外键必须引用的是主键或者唯一键(转载)
问: In SQL Server , I got this error -> "There are no primary or candidate keys in the refere ...
- 自定义HTTP消息拦截
/// <summary> /// HTTP消息拦截器 /// </summary> public class RequestHandler : DelegatingHandl ...
- Python面向对象封装案例
01. 封装 封装 是面向对象编程的一大特点 面向对象编程的 第一步 —— 将 属性 和 方法 封装 到一个抽象的 类 中 外界 使用 类 创建 对象,然后 让对象调用方法 对象方法的细节 都被 封装 ...