• 10.4 广州集训 Day3


    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 #include <iostream>
     2 
     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
    ", 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 #include <cstring>
      2 #include <vector>
      3 #include <string>
      4 #include <algorithm>
      5 #include <list>
      6 #include <set>
      7 #include <queue>
      8 #include <stack>
      9 #include <sstream>
     10 #include <numeric>
     11 #include <functional>
     12 #include <utility>
     13 #include <bitset>
     14 #include <iostream>
     15 #include <cmath>
     16 #include <map>
     17 
     18 using namespace std;
     19 
     20 #define MAXM 60
     21 #define MAXN 60
     22 
     23 #define DEBUG 0
     24 
     25 typedef long int  LINT;
     26 typedef long long INT64;
     27 
     28 typedef struct stProblem {
     29     int score;
     30     int state;
     31 } tProblem;
     32 tProblem problem[MAXM];
     33 
     34 typedef struct stOIer {
     35     int  id;
     36     LINT max;
     37     LINT min;
     38 } tOIer;
     39 tOIer oier[MAXN];
     40 
     41 int  p[MAXN];
     42 
     43 int  n, m, s, t;
     44 
     45 INT64 ans;
     46 
     47 INT64 calc_c(LINT m, LINT n) {
     48     if ((m < 0) || (n < 0))
     49         return 0;
     50     if (m == 0)
     51         return 1;
     52     if (n == 0)
     53         return 0;
     54     
     55     if (m > n)
     56         return 0;
     57     if (m == n)
     58         return 1;
     59     
     60     INT64 result = 1;
     61     for (int i = 0; i < n - m; ++i) {
     62         result = result * (n - i) / (1 + i);
     63     }
     64     
     65     return result;
     66 }
     67 
     68 void bubble_sort() {
     69     int bubble_sort_cmp(tOIer *a, tOIer *b);
     70     
     71     for (int i = 0; i < n - 1; ++i)
     72         for(int j = n - 1; j > i; --j)
     73             if (bubble_sort_cmp(oier + (j - 1), oier + j) < 0)
     74                 swap(oier[j - 1], oier[j]); // Defined in algorithm.h.
     75 }
     76 
     77 int bubble_sort_cmp(tOIer *a, tOIer *b) {
     78     if (a->max < b->max) {
     79         return -1;
     80     } else if (a->max == b->max) {
     81         return 0; 
     82         if (a->id > b->id)
     83             return -1;
     84         else
     85             return 1;
     86     } else { 
     87         return 1;
     88     }
     89 }
     90 
     91 int main(int argc, char *argv[]) {
     92     scanf("%d
    ", & m);
     93     
     94     LINT temp_score;
     95     for (int i = 0; i < m; ++i) {
     96         scanf("%ld
    ", & temp_score);
     97         if (temp_score > 0) {
     98             problem[i].score = temp_score;
     99             problem[i].state = 1;
    100         } else {
    101             problem[i].score = -temp_score;
    102             problem[i].state = 0;
    103         }
    104     }
    105     
    106     scanf("%d
    ", & n);
    107     
    108     char temp_state[MAXM];
    109     for (int i = 0; i < n; ++i) {
    110         oier[i].id = i;
    111         
    112         scanf("%s
    ", temp_state);
    113         for (int j = 0; j < m; ++j)
    114             if (problem[j].state) {
    115                 if ('Y' == temp_state[j]) {
    116                     oier[i].max += problem[j].score;
    117                     oier[i].min += problem[j].score;
    118                 }
    119             } else {
    120                 if ('Y' == temp_state[j])
    121                     oier[i].max += problem[j].score;
    122             }
    123     }
    124     
    125     scanf("%d
    ", & s);
    126     scanf("%d
    ", & t);
    127 
    128     bubble_sort(); // Max Score DESC Id ASC.
    129 
    130     for (int i = 0; i < n; ++i)
    131         for (int j = 0; j < i;
    132             p[i] += ((oier[j].min > oier[i].max)
    133                     || ((oier[j].min == oier[i].max) && (oier[j].id < oier[i].id))), ++j)
    134             ;
    135     
    136     #if DEBUG
    137         for (int i = 0; i < n; ++i)
    138             printf("%d(ID %d) : MAX(%d), MIN(%d) P(%d)
    ", i,
    139                     oier[i].id, oier[i].max, oier[i].min, p[i]);
    140         printf("
    ");
    141     #endif
    142     
    143     int k_min, k_max;
    144     ans = 0;
    145     for (int i = t - 1; i < n; ++i) {
    146         if (p[i] > s - 1)
    147            break;
    148         
    149         k_min = max(p[i] - s + t, 0);
    150         k_max = min(p[i], t - 1); // t - 1 - k >= 0
    151         
    152         #if DEBUG
    153             printf("STATE %d, MIN(%d), MAX(%d)
    ", i, k_min, k_max);
    154         #endif
    155         
    156         for (int k = k_min; k <= k_max; ++k)
    157             ans += calc_c(k, p[i]) * calc_c(t - 1 - k, i - p[i]);
    158     }
    159     
    160     printf("%lld
    ", ans);
    161 }

    //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 #include <algorithm>
     2 #include <cstdio>
     3 #include <cstring>
     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("
    %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
    ", ans ? 'N' : 'Y');
    56                 }
    57             }
    58         }
    59     }
    60 
    61     return 0;
    62 }

     

  • 相关阅读:
    java使用io流读取windows文件乱码问题
    java的io字符流关闭和刷新.flush();
    java使用io流实现图片复制
    java8新特性-函数式接口详细讲解及案例
    java8的lambda过滤list遍历集合,排序
    java复制对象,复制对象属性,只可复制两个对象想同的属性名。也可自定义只复制需要的属性。
    详讲KMP算法
    java栈和队列
    请求中文乱码解决
    idea创建servlet步骤
  • 原文地址:https://www.cnblogs.com/drizzly/p/7641855.html
Copyright © 2020-2023  润新知