并查集的一般操作 ④

RT

并查集一般操作最后一篇

原题 POJ1456

翻译:

给定N个商品,每个商品有利润Pi和过期时间di,每天只能卖一个商品,过期商品不能在卖,求如何安排每天买的商品,可以使收益最大。1≤N,pi,di≤10000.

发现,好像可以用贪心的想,从先要过期的商品中卖出利润大的;

就可以按时间排个序,然后依次按价格放入二叉堆中,每次用大的替换利润低的;

可以,不过这次想用另一种贪心策略。

我先卖利润大的商品,并且尽可能晚地卖出;

哦?...       interesting!

然后

我们就可以按利润排序,然后建立一个关于天数的并查集;

什么意思?就这个意思:

对于每个商品,若它在d天只有过期,就在并查集中查询d的根R,若R大于0,则安排在第R天卖出,然后把R并到R-1上(还是不懂可以手动模拟)

多思考。

#include <cstdio>
#include <algorithm>

using namespace std;

struct b
{
    int fa[10010];
    inline void be(int n){for(int i=0;i<=n;++i)fa[i]=i;return;}
    int f(int x){return fa[x]=fa[x]==x?x:f(fa[x]);}
    int u(int x,int y){return fa[f(y)]=f(x)-1;}    //把R并到R-1上
}a;
int n;
struct d
{
    int day,val;
    friend bool operator < (d a,d b)
    {
        return a.val > b.val;
    }
}num[10010];
int ans;
int main()
{
   // freopen("in","r",stdin);
    while(scanf("%d",&n)==1)
    {
        a.be(10005);
        for(int i=0;i<n;++i)
        {
            scanf("%d%d",&num[i].val,&num[i].day);
        }
        sort(num,num+n);         //按利润排序
        for(int i=0;i<n;++i)
        {
            int root=a.f(num[i].day);
            if(root>0)                          //如果有时间就卖
            {
                //printf("%d\n",a.f(num[i].day));
                a.u(num[i].day,num[i].day);
                ans+=num[i].val;
            }
        }
        printf("%d\n",ans);
        ans=0;
    }
}    

                                                                    11:34:22 2018-02-07

原文地址:https://www.cnblogs.com/AidenPearce/p/8425844.html

时间: 2024-10-30 23:01:22

并查集的一般操作 ④的相关文章

关于一般的并查集求根操作的一组对照研究

说道并查集,大家一定对于以多叉树状结构为基础的并查集并不陌生最常见的两种写法如下 1 private function getfat(x:longint):longint; 2 begin 3 while x<>c[x] do x:=c[x]; 4 exit(x); 5 end; 1 private function getfat(x:longint):longint; 2 begin 3 if x<>c[x] then exit(getfat(c[x])) else exit(x

HDU 2473 Junk-Mail Filter (并查集的删除操作)

Problem Description Recognizing junk mails is a tough task. The method used here consists of two steps: 1) Extract the common characteristics from the incoming email. 2) Use a filter matching the set of common characteristics extracted to determine w

并查集的删除操作

C - Junk-Mail Filter  HDU - 2473 题目大意:就是一堆信件,然后有两个操作,一个是把一堆信件归在一个文件夹,一个就是把一个信件从文件夹中取出,最后问有多少个文件夹,一开始所有信件都是单独的文件夹. 其实就是一个简单的并查集删除的操作,当删除时就创建新的结点来代替它,要注意的是数组的范围,虽然信件只有10的5次方,但是操作有10的6次方,因为删除时还得创建新节点,所以数组一定要开大,不然不是WR就是TL.最后的输出可以直接用set,也可以用数组标记信件是归在哪个文件夹

[HDOJ2473]Junk-Mail Filter(并查集,删除操作,马甲)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2473 给两个操作:M X Y:将X和Y看成一类. S X:将X单独划归成一类. 最后问的是有多少类. 并查集,但是带有删除操作.然而并查集本身不支持删除,网上说可以引入一个id来表示一个点.就好像一个人上网有很多小号一样,假如这个人的小号被封掉并且永久不能解封,还想继续玩下去的话那就重新建一个号,再生成一个id,表示这个id是这个人就好了. 注意在删除操作的时候不能把原来id的pre值重置. 1 /

zoj 3261 Connections in Galaxy War(并查集+离线逆向操作)

 题目:给出一些点,每个点有权值,然后有一些边,相连.无向的.然后有一些操作 query a.表示从a出发的能到达的所有点权值最大的点的编号(相同取编号最小,而且权值要比自己大) destory a,b 表示删除连接a,b的边 思路并查集,但是要逆向处理,所以先离线读入,从后向前处理,于是对于destroy操作,等价于连接两个点的操作,然后对于每个询问输出即可 #include<cstdio> #include<cstring> #include<cmath> #i

并查集的一般操作 ①

Rt 题目背景 A地区在地震过后,连接所有村庄的公路都造成了损坏而无法通车.政府派人修复这些公路. 题目描述 给出A地区的村庄数N,和公路数M,公路是双向的.并告诉你每条公路的连着哪两个村庄,并告诉你什么时候能修完这条公路.问最早什么时候任意两个村庄能够通车,即最早什么时候任意两条村庄都存在至少一条修复完成的道路(可以由多条公路连成一条道路) 输入输出格式 输入格式: 第1行两个正整数N,M 下面M行,每行3个正整数x, y, t,告诉你这条公路连着x,y两个村庄,在时间t时能修复完成这条公路.

并查集的一般操作 ②

RT 题目描述 明天就是母亲节了,电脑组的小朋友们在忙碌的课业之余挖空心思想着该送什么礼物来表达自己的心意呢?听说在某个网站上有卖云朵的,小朋友们决定一同前往去看看这种神奇的商品,这个店里有n朵云,云朵已经被老板编号为1,2,3,--,n,并且每朵云都有一个价值,但是商店的老板是个很奇怪的人,他会告诉你一些云朵要搭配起来买才卖,也就是说买一朵云则与这朵云有搭配的云都要买,电脑组的你觉得这礼物实在是太新奇了,但是你的钱是有限的,所以你肯定是想用现有的钱买到尽量多价值的云. 输入格式: 第1行n,m

HLJU 1105 cpc 喵喵的拆分集合 (并查集的逆向操作)

1105: 喵喵的拆分集合 Time Limit: 1 Sec  Memory Limit: 128 MB Submit: 37  Solved: 8 [Submit][Status][Web Board] Description 众所周知,DoubleQ是DS(Data Structure)粉,她最爱DS了.现在她要实现一个神奇的DS,支持下列两个操作: -删除某条边,表示为"D x",即为删除第x条边 -查询两点是否属于一个集合,表示为"Q a b",即为查询节

朋友(并查集的删除操作 可看作是插入操作的逆序)

小 z 被选为他们村的村长, 现在小 z 调查他们村上的关系. 如果村民 a 和村民 b 是朋友, 村民 b 和村民 c 是朋友, 那么村民 a 和村民 c 也是朋友. 那么村上的村民就会形成一个"朋友" 团队, 现在小 z 想知道他们村长有多少个这样的团队. 同时, 他们村会有人离开村子到城里谋求发展, 那么小 z 也想知道, 当他们离开后村上的"朋友" 团队.★数据输入输入第一行包括两个整数, N, M. N 表示一共有 N 个人, M 表示一个共有M 对关系.