[传送门]

题目即求所有的三元组,相对大小关系同 $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的更多相关文章

  1. Codechef August Challenge 2019 Division 2

    Preface 老年菜鸡终于开始打CC了,由于他太弱了所以只能打Div2 因为台风的原因challenge并没有写,所以水了个Rank7 A Football SB模拟题不解释 #include< ...

  2. Codechef August Challenge 2018 : Chef at the River

    传送门 (要是没有tjm(Sakits)的帮忙,我还真不知道啥时候能做出来 结论是第一次带走尽可能少的动物,使未带走的动物不冲突,带走的这个数量就是最优解. 首先这个数量肯定是下界,更少的话连第一次都 ...

  3. 【CodeChef】August Challenge 2019 Div2 解题报告

    点此进入比赛 \(T1\):Football(点此看题面) 大致题意: 求\(max(20a_i-10b_i,0)\). 送分题不解释. #include<bits/stdc++.h> # ...

  4. Codechef April Challenge 2019 游记

    Codechef April Challenge 2019 游记 Subtree Removal 题目大意: 一棵\(n(n\le10^5)\)个结点的有根树,每个结点有一个权值\(w_i(|w_i\ ...

  5. 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] 表示第 ...

  6. 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 ...

  7. CF&&CC百套计划2 CodeChef December Challenge 2017 Chef And his Cake

    https://www.codechef.com/DEC17/problems/GIT01 #include<cstdio> #include<algorithm> using ...

  8. CodeChef April Challenge 2019题解

    传送门 \(Maximum\ Remaining\) 对于两个数\(a,b\),如果\(a=b\)没贡献,所以不妨假设\(a<b\),有\(a\%b=a\),而\(b\%a<a\).综上, ...

  9. Codechef October Challenge 2019 Division 1

    Preface 这次CC难度较上两场升高了许多,后面两题都只能借着曲明姐姐和jz姐姐的仙气来做 值得一提的是原来的F大概需要大力分类讨论,结果我写了一大半题目就因为原题被ban了233 最后勉强涨了近 ...

随机推荐

  1. The Preliminary Contest for ICPC Asia Nanjing 2019/2019南京网络赛——题解

    (施工中……已更新DF) 比赛传送门:https://www.jisuanke.com/contest/3004 D. Robots(期望dp) 题意 给一个DAG,保证入度为$0$的点只有$1$,出 ...

  2. 微软官方关于 Windows To Go 的常见问题

    Windows To Go:常见问题 2016/04/01 本文内容 什么是 Windows To Go? Windows To Go 是否依赖虚拟化? 哪些人员应该使用 Windows To Go? ...

  3. 百度前端技术学院task15源代码

    这一道题涉及到排序,读取页面内容,输出显示到某一节点当中以及添加事件. 刚开始一直在想怎么获取某一节点的内容,后面采用的是sdata.childNodes,获取所有的节点.再通过schildNode[ ...

  4. vue截取字符串

    1.vue中截取前11位字符串 <li> <span>立案时间:</span> <p>{{jsyd.TIME.substring(0,10)}}< ...

  5. SQL系列(六)—— 过滤(where)

    在日常的应用中的,大多数业务场景都只是需要特定的数据,所以能够过滤筛选数据显得尤为至关重要.从需求角度分析,需要特定的数据,即需要一定条件的数据,即从全量数据中根据特定条件过滤出需要的数据. 如果需要 ...

  6. IP地址和MAC地址绑定的必要性

    计算机网络是一个共通的网络,世界上任何计算机都可以互相访问. 实现的原理基于网络通讯的互联网交互五层模型. 计算机网络的历史发展 当计算机网络技术初始利用的时代,几台计算机通过集线器连接,就可以实现网 ...

  7. Windows服务的安装及配合定时器编写简单的程序

    最近要实时统计一些数据,所以就用到了Windows服务及定时任务,在这里记录下. Windows Service简介: 一个Windows服务程序是在Windows操作系统下能完成特定功能的可执行的应 ...

  8. javascript:void(0)的含义

    void关键字介绍 首先,void关键字是javascript当中非常重要的关键字,该操作符指定要计算或运行一个表达式,但是不返回值. 语法格式: void func() void(func()) 实 ...

  9. Js字符串用法

    js字符串整理导向图 ---欢迎收藏^ - ^

  10. windows ssh远程登录阿里云遇到permissions are too open的错误

    我试图用ssh -i 命令远程登录阿里云时,遇到如下错误: Permissions for 'private-key.ppk' are too open. It is required that yo ...