zoukankan      html  css  js  c++  java
  • ccf-201909-04

     题意:有m个种类,每个种类有n个物品。每个物品有自己的种类、编号、分数。要在所有物品中选出不超过sum个的物品。

    按以下方式选择:①按分数排序,分数大的在前  ②分数相同的,种类小的在前 ③分数相同,种类相同,编号小的在前

    每个种类可以选择的物品数量不得超过count[i]个,总的可以选择的物品数量不得超过sum个

    每个种类一行,输出该种类所选择的物品的编号。如何该种类没有物品被选,则输出-1

    有三种操作:①增加结点  ②删除结点  ③输出所选择的物品编号

    注意:m<=50,n<=30000,但是id<=10^9。虽然物品的种类只有50种,每类物品的个数只有30000,但是物品的编号有10^9个。(编号并不是按物品的个数来计算的)

       操作2只给type和id,所以需要映射。因为id<=1e9,所以用二维数组存a[type][id]=score是不可行的。要用unordered_map映射

    思路:

    ①用 ID = type * 1e9 + id 唯一标识一个物品的编号,用set<Node> s存放所有的物品,在Node里定义 id, score, 以及set的排序方式。set会自动排序,所以不用sort一遍,否则会出错。

    ②用unordered_map<long long, set<Node>:: iterator> Map来存物品的ID和物品在set中的迭代器的映射,用来在删除set内部元素。向set增加元素时,用Map[ID]=s.insert(x).first来获取映射关系,时间复杂度O(1)。如果用遍历set的方法删除元素,O(n),会超时。

    ③用vector来存每个type所选的物品的id。set的结构体里没有存type,id,那么要如何获取type和id?

       因为ID =  type * 1e9 + id,所以type = ID / 1e9,  id = ID % 1e9, 注意:因为ID是long long,所以设置const long long INF = 1e9

    知识点:

    *** insert函数的返回值是一个pair,first成员就是指向新插入的元素在set中位置的迭代器,second成员是一个bool表示这次插入操作是否成功

    ①关联容器包括:set、map
    标准库提供set关联容器分为:
    (1)按关键字有序保存元素:set(关键字即值,即只保存关键字的容器);multiset(关键字可重复出现的set);
    (2)无序集合:unordered_set(用哈希函数组织的set);unordered_multiset(哈希组织的set,关键字可以重复出现)。

    ②在set中每个元素的值都唯一,而且系统能根据元素的值自动进行排序。set中元素的值不能直接被改变。set内部采用的是一种非常高效的平衡检索二叉树:红黑树,也称为RB树(Red-Black Tree)。RB树的统计性能要好于一般平衡二叉树。

    ③set具备的特点:
    (1)set中的元素都是排序好的
    (2)set中的元素都是唯一的,没有重复的

    ④map:红黑树结构,自动排序

    ⑤map<class T1,class T2> :存储T1->T2映射的键值对,map先按照T1升序排序,再按T2升序排序,其中T1,T2可以是任意类(如:int、string、char或自定义类),T1值唯一,其插入删除的时间复杂度为O(log2)

    ⑥unordered_map<class T1,class T2>特性: 仅存储T1->T2映射的键值对,T1值唯一,其插入和删除的时间复杂度为O(1)

    ⑦unordered_map 无序映射:比map快(用map会超时)

    ⑧unordered_map 在C++ 11 才可以用,否则会编译出错

    #include <bits/stdc++.h> 
    #define MAX 51
    
    using namespace std;
    
    
    struct Node{
        long long id;
        int score;
        bool operator < (const Node &b)    const{                //Set要内部排序,用struct写set,需要在struct内重写排序方法 
            if(score!=b.score)    return    score > b.score;
            else    return id < b.id; 
        }
    };
    
    
    
    set <Node> s;        //用set存放所有物品信息    
    vector<int> r[MAX];
    unordered_map<long long, set<Node>::iterator> Map;        //key:type*10^9 + id;  value:物品在set中的迭代器  ||用type * 1e9 +id 唯一标识一个物品的序号  
    int m;        //物品种类 
    int n;        //物品个数 
    int sum;    //总的不能超过的个数 
    int Count[MAX];        //每类物品不得超过的个数 
    const long long INF = 1e9;      //因为ID是long long,并且要取模,所以要将1e9也设置为long long 
    
    
    
    void op(){
        int cont =0;
        for(int i=0;i<MAX;i++)
            r[i].clear(); 
        for(set<Node>::iterator it =s.begin();  it!=s.end(); it++){
            if(sum==0)    break;
            Node a=*it;
            int type =a.id / 1e9;
            int id =a.id % INF;            //long long % long long
            if(Count[type]>0){        //该种类还可以选 
                Count[type]--;
                r[type].push_back(id);
                sum--;
                }
            }    
        for(int i=0;i<m;i++){
            int len=r[i].size();
            if(len!=0){
                for(int j=0;j<len;j++){
                    if(j!=len-1)    printf("%d ",r[i][j]);
                    else printf("%d
    ",r[i][j]);
                }
            }
            else    printf("-1
    ");
        }
    }
    
    
    int main(){
        int type,id,score,c,q;
        Node x;
        while(scanf("%d %d",&m,&n)!=EOF){
            s.clear();
            memset(Count,0,sizeof(Count));
            for(int i=1;i<=n;i++){
                scanf("%d %d",&id,&score);    
                x.score=score;
                for(int j=0;j<m;j++){
                    x.id=j*1e9 + id;    
                    long long key=j*1e9+id;
                    Map[key]=s.insert(x).first;
                }
            }
            scanf("%d",&q);
            for(int i=0;i<q;i++){
                scanf("%d",&c);
                if(c==1){
                    scanf("%d %d %d",&type,&id,&score);
                    x.id=type*1e9 + id;     x.score=score;
                    long long key=type*1e9+id;
                    Map[key]=s.insert(x).first;        //向Set插入元素 
                }
                else if(c==2){
                    scanf("%d %d",&type,&id);                //set.erase()提供了4种重载,分别可以通过key,或者迭代器,或者迭代器范围来删除元素。
                    long long k=type*1e9+id;
                    s.erase(Map[k]);                //根据元素的迭代器,删除Set中的元素 
                    Map.erase(k);                //删除物品在Map中的映射 
                                                //s.erase(Node{type,id,score});            //为什么出错?                        
                }
                else if(c==3){
                    scanf("%d",&sum);
                    for(int i=0;i<m;i++){
                        scanf("%d",&Count[i]);        //第i个种类不得超过count[i]个 
                    }
                    op();
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    codeforces 814B An express train to reveries
    codeforces 814A An abandoned sentiment from past
    codeforces 785D D. Anton and School
    codeforces 785C Anton and Fairy Tale
    codeforces 791C Bear and Different Names
    AOP详解
    Spring集成JUnit测试
    Spring整合web开发
    IOC装配Bean(注解方式)
    IOC装配Bean(XML方式)
  • 原文地址:https://www.cnblogs.com/shiliuxinya/p/12032232.html
Copyright © 2011-2022 走看看