• zoj 3963 heap partion


    https://vjudge.net/problem/ZOJ-3963

    题意:

    给出一个数列,可以用这个数列构造一种二叉树,这个二叉树满足数的下标 i <= j,并且 si <= sj,si是sj的父亲,问给出的数列可以构造多少棵这样的二叉树。

    思路:

    这题赛上没有写出来,看了题解之后给补的。

    首先,通过这题学到了,memset初始化数组有时是会造成超时的。set的upper_bound(x)这个函数,它返回set中大于x的第一个元素的位置(注意是大于,不是大于等于)。

    于是,这题就是贪心加set。贪心指的是对于当前的输入的x,在前面找到小于等于它的数,如果说没有找到,那么就把这个数插入,作为一棵新的树的根。如果说找到了,那么就把这个点插入这棵树,并且把这个数可插入的数量减1,当数量为0的时候就不能再插入了。具体看看注释。

    代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <vector>
      4 #include <set>
      5 #include <algorithm>
      6 using namespace std;
      7 
      8 int num,node[100005],cnt[100005];//node保存节点x的编号,cnt数组表示每个节点能插入的剩下的位置
      9 
     10 vector<int> ans[100005];//ans保存答案
     11 set<int> s;
     12 
     13 void solve(int x,int pos)
     14 {
     15     set<int>::iterator it;
     16 
     17     it = s.upper_bound(x);
     18 
     19     if (it == s.begin())//x是最小的,所以选择插入
     20     {
     21         s.insert(x);
     22 
     23         cnt[x] = 2;//一开始有两个空位
     24 
     25         node[x] = num;
     26 
     27         ans[node[x]].push_back(pos);
     28 
     29         num++;
     30     }
     31     else
     32     {
     33         --it;//因为是大于x的位置,所以要--
     34 
     35         if (x == (*it))//相等,就不用插入,旧的元素
     36         {
     37 
     38             cnt[x]++;//相当于是加了2个位置,然后自己又占了一个
     39 
     40             ans[node[x]].push_back(pos);
     41         }
     42         else
     43         {
     44             node[x] = node[*it];
     45 
     46             cnt[*it]--;
     47 
     48             if (cnt[*it] == 0) s.erase(*it);//没有位置了,删除
     49 
     50             cnt[x] = 2;//新的元素
     51 
     52             s.insert(x);//后面插入是防止迭代器改变
     53 
     54             ans[node[x]].push_back(pos);
     55         }
     56     }
     57 }
     58 int main()
     59 {
     60     int t;
     61 
     62     scanf("%d",&t);
     63 
     64     while (t--)
     65     {
     66 
     67         s.clear();
     68 
     69         num = 0;
     70 
     71         int n;
     72 
     73         scanf("%d",&n);
     74 
     75         for (int i = 0;i <= n;i++)
     76         {
     77             node[i] = cnt[i] = 0;
     78             ans[i].clear();//说了n的总和不超过2 * 10 ^ 6,用memeset反而会超时
     79         }
     80 
     81         for (int i = 1;i <= n;i++)
     82         {
     83             int x;
     84 
     85             scanf("%d",&x);
     86 
     87             solve(x,i);
     88         }
     89 
     90         printf("%d
    ",num);
     91 
     92         for (int i = 0;i < num;i++)
     93         {
     94             int sz = ans[i].size();
     95 
     96             printf("%d",sz);
     97 
     98             for (int j = 0;j < sz;j++)
     99             {
    100                 printf(" %d",ans[i][j]);
    101             }
    102 
    103             printf("
    ");
    104         }
    105     }
    106 
    107     return 0;
    108 }
  • 相关阅读:
    17-canvas绘制扇形
    16-canvas绘制圆弧
    15-canvas渐变色
    14-canvas绘制柱状图
    13-绘制矩形的简写方式
    12-es6类的方式封装折线图
    11-canvas绘制折线图
    10-canva绘制数据点
    jenkins 环境部署 (yum安装方式)
    BerkeleyDB安装
  • 原文地址:https://www.cnblogs.com/kickit/p/7226028.html
Copyright © 2020-2023  润新知