zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    Saltstack module gem 详解
    Saltstack module freezer 详解
    Saltstack module firewalld 详解
    Saltstack module file 详解
    Saltstack module event 详解
    Saltstack module etcd 详解
    Saltstack module environ 详解
    Saltstack module drbd 详解
    Saltstack module dnsutil 详解
    获取主页_剥离百度
  • 原文地址:https://www.cnblogs.com/kickit/p/7226028.html
Copyright © 2011-2022 走看看