bst
【问题描述】
二叉查找树是一种特殊的二叉树(每个节点最多只有两个儿子的树)。树的每个节点上存有一个唯一的值,并且满足:这个节点的左子树内所有点的值都比这个节点的值小,且右子树内所有点的值都比这个节点的值要大。
对于一棵二叉查找树T,我们可以将一个值为x的新点插入T中,且保持树的性质。
算法如下:
需要将x插入树T时,执行insert(x, T.root) 。
现在有N个数需要插入一棵空树中。给定插入序列,请在每个元素被插入之后,输出所有节点的深度总和(根的深度为0)。
【输入格式】
输入的第一行一个整数 n,表示序列长度。
以下 n 行是序列中的数字,这些数字是各不相同的,在[1, n]区间。
【输出格式】
输出 n 行,第 i 行整数表示第 i 个数插入树后,至这个节点的节点深度总和。
【样例输入】
8
3
5
1
6
8
7
2
4
【样例输出】
0
1
2
4
7
11
13
15
【数据规模与约定】
对于 50%的数据, 满足N ≤ 1000
对于100%的数据,满足N ≤ 3 ∗ 10^5 。
Solution:
双向链表+DP。(也可以说是个模拟)
和字面意思上一样是一个treap。
我们考虑:当x=a[i]被插入的时候,假设T(二叉搜索树)中比x小的最大元素是p,比x大的最小元素是q。显然,p,q一定相连(可以证明)。
(证明:p,q之间不存在其他元素,谁在父亲取决于谁先插入。)
我们设f[i]表示x插入的深度,可得f[i]=Max(f[p],f[q])+1。
即转化为求p,q。
怎么求呢?
可以用双向链表存1~n,每次删除一个元素,删除时的前驱和后继就是p,q。
这个问题就解决了。(其实也就是模拟一下treap)
Other:
现场还有大佬对着排序数组按时间戳建笛卡尔树A了此题,大概不会打...
1 #include2 3 #define MAXN 300005 4 5 int n; 6 int a[MAXN]; 7 int prev[MAXN], next[MAXN]; 8 int u[MAXN], v[MAXN]; 9 int deep[MAXN]; 10 11 int main(void) 12 { 13 14 scanf("%d", & n); 15 for (int i = 1; i <= n; ++i) 16 scanf("%d", a + i); 17 18 for (int i = 1; i <= n; ++i) 19 { 20 prev[i] = i - 1; 21 next[i] = i + 1; 22 } 23 24 int x; 25 for (int i = n; i > 1; --i) 26 { 27 x = a[i]; 28 u[x] = prev[x]; 29 v[x] = next[x]; 30 next[prev[x]] = next[x]; 31 prev[next[x]] = prev[x]; 32 } 33 34 long long sum = 0; 35 for (int i = 1; i <= n; ++i) 36 { 37 x = a[i]; 38 39 if ((u[x] >= 1) && (u[x] <= n)) 40 if (deep[x] < deep[u[x]] + 1) 41 deep[x] = deep[u[x]] + 1; 42 if ((v[x] >= 1) && (v[x] <= n)) 43 if (deep[x] < deep[v[x]] + 1) 44 deep[x] = deep[v[x]] + 1; 45 46 sum += deep[a[i]]; 47 48 printf("%lld\n", sum); 49 } 50 51 return 0; 52 }
ctsc:
【问题描述】
n 人参加信息学竞赛,共有 m 道题。现在比赛已经结束,评分正在进行中,对于已经结束评测的试题,已知每名考生这道题的答案是否正确,对于未结束评测的试题,只知道每名考生是否提交答案。每个题分数固定,提交正确的答案的考生可以得到这一题的分数,分数越高排名越靠前,分数相同编号小的考生排名靠前。这 n 人中,排名最靠前的 s 人将获得入选代表队的资格,而这 s 个中将通过最终的科学委员会面试选出其中的 t 个人。输入当前的评测信息(包括是否ᨀ交,以及已经评测部分的是否正确)以及每道题的分值,问最终的 t 人代表队共有多少种组队的可能。
【输入格式】
输入文件第一行是 m,接下去 m 行每行一个整数来表示每道题目的分值(整数是正的表示该题已经评测,否则表示该题尚未评测,该题目的分值为这个整数的绝对值)。然后是一个整数 n,接下去是一个 n 行 m 列的字母阵,字母阵只包含 YN 两种字母(Yes or No),如果第 i 题已经完成评测,那么这个字母矩阵中第 j 行第 i 列的表示第 j 名选手的第 i 题是否已经得分;如果第 i 题尚未完成评测,那么这个字母矩阵中第 j 行第 i 列的表示第 j 名选手的第 i 题是否提交了解答。接下来两个整数s,t如题意。
【输出格式】
输出文件只有一行,即为最终的 t 人代表队的组队方案数。
【样例输入】
2
1
-10
4
NY
YN
YN
YN
3
2
【样例输出】
5
【数据规模与约定】
对于100%的数据, 满足1 ≤N, M ≤ 50。
Solution:
Other:
据说是最简单的组合数呢。
考场玩了一个多小时也没证明出来。
所以留坑...?
1 #include2 #include 3 #include <string> 4 #include 5 #include 6 #include <set> 7 #include
8 #include 9 #include 10 #include 11 #include 12 #include 13 #include 14 #include 15 #include 16 #include
//std画风有点神奇我也不太懂...留坑等待更新自己der
history
【问题描述】
zhx 不喜欢研究历史,但是 dhh 是历史大师。
【问题描述】
历史学家dhh正在研究一个奇怪的王国的历史。当前阶段的任务是研究该国的交通。
根据这个奇怪的王国的史书记载,史书开始记载前这个王国有n个城市(城市从0开始标号),但所有城市之间都没有道路相连。
每一年,在位的国王会修建一条双向道路x<->y(x!=y),一条道路可能被修建多次。
而在这之间,国王会计划进行若干次旅行。对于计划进行的一次旅行st->ed,如果当时能完成这次旅行,而t年前不能完成这次旅行,那么国王会对之前的建设成果感到满意,否则他会很生气,并在他感到满意之前(包括使他满意的那次旅行)都让史官记录下错误的信息,怎么样得到正确信息将在输入格式中描述。
当然在这些年中也发生了若干次国王的交替,而每个国王的c值不一定相同,但在国王在位期间c值不会改变(初始国王的c值为0,其他的c值可通过记载得到),新上位的国王开始处于不生气的状态。
请根据史书帮助DHH得出国王每次对于计划旅行是否满意,从而使DHH能够研究该国的交通。
【输入格式】
输入多组数据,到EOF结束。
每组数据第一行两个整数n,m,表示初始城市数和史书记载的内容数。
接下来m行,每行是以下三种格式之一:
1.K v,表示国王交替,如果被替换的国王是生气的(即这个是错误信息),那么新国王的c值为 v+被替换的国王的值,否则新国王的c值为v。
2.R x y,表示史书上记载的是国王修建了x<->y的道路,如果这是错误信息,那么真实信息为 (x+c)%n <-> (y+c)% n的道路。
3.T st ed t,表示国王计划进行的一次st->ed的旅行,且比较的是t年前的情况(国王可能会和史书开始记载以前的情况比较),如果这是错误信息,那么真实信息为国王计划进行的一次 (st+c)%n -> (ed+c)%n 的旅行,且比较的是(t+c)%n年前的情况。
注意只有遇到R操作才会使年份的计数+1。
【输出格式】
每组数据对于每个T的记录输出一行,如果此次计划旅行令国王满意,则输出Y,否则输出N。样
【样例输入】
3 7 R 0 1 T 0 1 1 K 1 R 0 1 T 0 1 1 R 0 1 T 1 2 0
【样例输出】
Y N Y
【数据规模与约定】
n,m ≤ 3 × 10^5 , 0 ≤ v,x,y,st,ed < n , 0 ≤ t < m,数据组数≤ 10
Solution:
// blog坑填不完了。。。先贴std,不然空着好像不太好
1 #include2 #include 3 #include 4 5 using namespace std; 6 7 #define rep(i, n) for (int i = 0; i < n; ++i) 8 9 const int MaxN = 300005; 10 11 int f[MaxN], g[MaxN], h[MaxN]; 12 int n, m; 13 long long c; 14 bool ans; 15 char opr[50000]; 16 17 int get(int x, int t) { 18 while (f[x] >= 0 && g[x] <= t) x = f[x]; 19 return x; 20 } 21 22 void merge(int x, int y, int t) { 23 x = get(x, t); 24 y = get(y, t); 25 if (x != y) { 26 if (h[x] > h[y]) swap(x, y); 27 f[x] = y, g[x] = t; 28 h[y] += (h[x] == h[y]); 29 } 30 } 31 32 int main(void) { 33 freopen("history.in","r",stdin); 34 freopen("history.out","w",stdout); 35 int t, x, y, z, v; 36 37 while (scanf("%d%d", &n, &m) != EOF) { 38 rep(i, n) h[i] = 1, f[i] = -1; 39 t = c = ans = 0; 40 while (m--) { 41 scanf("\n%s", opr); 42 if (*opr == 'K') 43 scanf("%d", &v), c = c * ans + v, ans = 0; 44 else { 45 scanf("%d%d", &x, &y); 46 x = (c * ans + x) % n; 47 y = (c * ans + y) % n; 48 49 if (*opr == 'R') { 50 merge(x, y, ++t); 51 } else { 52 scanf("%d", &z); 53 z = (c * ans + z) % n; 54 ans = ((get(x, t) == get(y, t)) == (get(x, t - z) == get(y, t - z))); 55 printf("%c\n", ans ? 'N' : 'Y'); 56 } 57 } 58 } 59 } 60 61 return 0; 62 }