[hdu5360]贪心

题意:一个人想邀请n个人出去玩,假设当前同意和他一起去的人数为cnt,那么他去邀请i的时候,i同意的条件是L[i]<=cnt<=R[i],L[i],R[i]是给定的,问怎样安排邀请顺序,使得有最多的人同意

思路:由于同意他的条件是cnt,不妨在当前状态下将所有没被邀请的人分成3类,一种是R[i]<cnt的,一种是L[i]<=cnt<=R[i]的,一种是L[i]>cnt的,对于第一种已经不可能同意了,因为cnt是递增的,对于第三种现在根本不用考虑,而对于第二种,那么都可以被邀请,且被邀请了一定会同意。明显应该邀请R[i]最小的,因为他们总是比其他人最先变成第一种人。于是得到一个贪心算法,每次选择L[i]<=cnt的所有没邀请的人中R[i]最小的。而这可以每次在cnt发生变化时,用set来维护第二种人的集合,并可以在logn的时间内找到R[i]最小的。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

#include <map>

#include <set>

#include <cmath>

#include <ctime>

#include <deque>

#include <queue>

#include <stack>

#include <vector>

#include <cstdio>

#include <string>

#include <cstdlib>

#include <cstring>

#include <iostream>

#include <algorithm>

using namespace std;

#define X                   first

#define Y                   second

#define pb                  push_back

#define mp                  make_pair

#define all(a)              (a).begin(), (a).end()

#define fillchar(a, x)      memset(a, x, sizeof(a))

typedef long long ll;

typedef pair<intint> pii;

typedef unsigned long long ull;

#ifndef ONLINE_JUDGE

void RI(vector<int>&a,int n){a.resize(n);for(int i=0;i<n;i++)scanf("%d",&a[i]);}

void RI(){}void RI(int&X){scanf("%d",&X);}template<typename...R>

void RI(int&f,R&...r){RI(f);RI(r...);}void RI(int*p,int*q){int d=p<q?1:-1;

while(p!=q){scanf("%d",p);p+=d;}}void print(){cout<<endl;}template<typename T>

void print(const T t){cout<<t<<endl;}template<typename F,typename...R>

void print(const F f,const R...r){cout<<f<<", ";print(r...);}template<typename T>

void print(T*p, T*q){int d=p<q?1:-1;while(p!=q){cout<<*p<<", ";p+=d;}cout<<endl;}

#endif

template<typename T>bool umax(T&a, const T&b){return b<=a?false:(a=b,true);}

template<typename T>bool umin(T&a, const T&b){return b>=a?false:(a=b,true);}

template<typename T>

void V2A(T a[],const vector<T>&b){for(int i=0;i<b.size();i++)a[i]=b[i];}

template<typename T>

void A2V(vector<T>&a,const T b[]){for(int i=0;i<a.size();i++)a[i]=b[i];}

const double PI = acos(-1.0);

const int INF = 1e9 + 7;

/* -------------------------------------------------------------------------------- */

const int maxn = 1e5 + 7;

const int M = 1e9;

struct Node {

    int L, R, id;

    bool operator < (const Node &that) const {

        return R < that.R;

    }

    Node(int L, int R, int id): L(L), R(R), id(id) {}

    Node() {}

};

multiset<Node> S;

int L[maxn], R[maxn];

pii node[maxn];

vector<int> G[maxn];

int main() {

#ifndef ONLINE_JUDGE

    freopen("in.txt""r", stdin);

    //freopen("out.txt", "w", stdout);

#endif // ONLINE_JUDGE

    int T;

    cin >> T;

    while (T --) {

        int n;

        cin >> n;

        S.clear();

        for (int i = 0; i <= n; i ++) {

            G[i].clear();

        }

        for (int i = 0; i < n; i ++) {

            scanf("%d", L + i);

            G[L[i]].pb(i);

        }

        for (int i = 0; i < n; i ++) {

            scanf("%d", R + i);

            node[i] = mp(L[i], R[i]);

        }

        for (int i = 0; i < G[0].size(); i ++) {

            int id = G[0][i];

            S.insert(Node(node[id].X, node[id].Y, id));

        }

        vector<int> ans;

        vector<bool> vis(n);

        int cnt = 0;

        while (1) {

            multiset<Node>::iterator iter = S.lower_bound(Node(0, cnt, 0));

            if (iter == S.end()) break;

            ans.pb((*iter).id);

            vis[(*iter).id] = true;

            S.erase(iter);

            cnt ++;

            for (int i = 0; i < G[cnt].size(); i ++) {

                int id = G[cnt][i];

                S.insert(Node(node[id].X, node[id].Y, id));

            }

        }

        for (int i = 0; i < n; i ++) {

            if (!vis[i]) ans.pb(i);

        }

        printf("%d\n", cnt);

        for (int i = 0; i < n; i ++) {

            printf("%d%c", ans[i] + 1, i == n - 1? ‘\n‘ ‘ ‘);

        }

    }

    return 0;

}

时间: 2024-10-12 03:11:04

[hdu5360]贪心的相关文章

hdu5360 (贪心+优先队列)

做法是每次选取起始条件符合,并且结束条件最早的.(每个人的起始时间为l,结束时间为r) #include <iostream> #include <stdio.h> #include <memory.h> #include <queue> #include <vector> using namespace std; int N,T; struct node { int start; int End; int index; bool friend

hdu5360||多校联合第6场1008 贪心

http://acm.hdu.edu.cn/showproblem.php?pid=5360 Problem Description There are n soda conveniently labeled by 1,2,-,n. beta, their best friends, wants to invite some soda to go hiking. The i-th soda will go hiking if the total number of soda that go hi

【uva 1615】Highway(算法效率--贪心 区间选点问题)

题意:给定平面上N个点和一个值D,要求在x轴上选出尽量少的点,使得对于给定的每个店,都有一个选出的点离它的欧几里德距离不超过D. 解法:先把问题转换成模型,把对平面的点满足条件的点在x轴的直线上可得到一个个区间,这样就是选最小的点覆盖所有的区间的问题了.我之前的一篇博文有较详细的解释:关于贪心算法的经典问题(算法效率 or 动态规划).代码实现我先空着.挖坑~

【贪心+Treap】BZOJ1691-[Usaco2007 Dec]挑剔的美食家

[题目大意] 有n头奶牛m种牧草,每种牧草有它的价格和鲜嫩度.每头奶牛要求它的牧草的鲜嫩度要不低于一个值,价格也不低于一个值.每种牧草只会被一头牛选择.问最少要多少钱? [思路] 显然的贪心,把奶牛和牧草都按照鲜嫩度由大到小排序,对于每奶牛把鲜嫩度大于它的都扔进treap,然后找出后继. 不过注意后继的概念是大于它且最小的,然而我们这里是可以等于的,所以应该是找cow[i].fresh-1的后继,注意一下…… 1 #include<iostream> 2 #include<cstdio&

POJ1017 Packets(贪心算法训练)

Time Limit: 1000MS          Memory Limit: 10000K          Total Submissions: 51306          Accepted: 17391 Description A factory produces products packed in square packets of the same height h and of the sizes 1*1, 2*2, 3*3, 4*4, 5*5, 6*6. These pro

ZOJ 3946 Highway Project 贪心+最短路

题目链接: http://www.icpc.moe/onlinejudge/showProblem.do?problemCode=3946 题解: 用dijkstra跑单元最短路径,如果对于顶点v,存在一系列边(ui,v)使得dis[v]最小(dis[v]表示0到v的距离).这些边能且只能选一条,那么我们自然应该选cost最小的那个边了. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #inc

CoderForce 140C-New Year Snowmen(贪心)

题目大意:有n个已知半径的雪球.堆一个雪人需要三个尺寸不同的雪球,问用这些雪球最多能堆多少个雪人? 题目分析:先统计一下每种尺寸的球的个数,从三种最多的种类中各取出一个堆成雪人,这样贪心能保证的到的数目最多. 代码如下: # include<iostream> # include<map> # include<vector> # include<cstdio> # include<queue> # include<algorithm>

计蒜客 跳跃游戏(贪心)

给定一个非负整数数组,假定你的初始位置为数组第一个下标.数组中的每个元素代表你在那个位置能够跳跃的最大长度. 请确认你是否能够跳跃到数组的最后一个下标. 例如: A = [2,3,1,1,4], return ture A = [3,2,1,0,4], return false. 格式: 第一行输入一个正整数n,接下来的一行,输入数组A[n].如果能跳到最后一个下标,输出"true",否则输出"false" 样例1 ????输入:???? ????????5 ???

BZOJ 2525 [Poi2011]Dynamite 二分+树形贪心

题意: n个点,一棵树,有些点是关键点,可以将m个点染色. 求所有关键点到最近的被染色点的距离的最大值最小. 解析: 反正从这道题我是学了一种做题思路? 大爷讲课的时候说的:一般选择某些点的代价相同的话都是贪心,代价不同的话一般都是DP. 想想也挺对的,不过就是没有感悟到过? 反正这题考试的时候我是直接D了贪心的- -! 忘了为啥D了. 显然最大值最小我们需要二分一下这个值. 然后接下来我们从下往上扫整棵树. 节点的状态有几个? 第一种是 子树内没有不被覆盖的关键点,并且子树中有一个节点的贡献可