{题解}[jzoj4064]【JSOI2015】套娃(doll)

来源:互联网 发布:苹果抹掉数据能恢复吗 编辑:程序博客网 时间:2024/05/01 13:05

传送门

Analysis

直接考虑答案

Ans=IiBiAiBi

其中Ai指i所匹配的out的大小。
显然,为使Ans最小,要使AiBi尽量大。
剩下的,也就没什么了。
对于一个尽量大的Bi,选择一个尽量大的Oj
至于实现的话…别人都跟我说使用线段树。
但是我会O(n)[不包含排序],为什么要用O(n log n)
比如说,既然一个选择不会被其他的选择影响,那我们可以直接统排了Oi
剩下的自己YY,YY不出来看代码。
–思考时间–

Code

#include <cstdio>#include <cstring>#include <iostream>#include <algorithm>#define oo 2139062143using namespace std;const long long N = 200200, NUM = 10100;long long n,ans;struct node{    long long i,o,b;}a[N],b[N];long long t[N],mxnm,fa[N];long long read(long long &n){    char ch=' ';long long q=0,w=1;    for(;(ch!='-')&&((ch<'0')||(ch>'9'));ch=getchar());    if(ch=='-')w=-1,ch=getchar();    for(;ch>='0' && ch<='9';ch=getchar())q=q*10+ch-48;n=q*w;return n;}bool cmpb(node a,node b){    return a.b > b.b;}long long max(long long a,long long b){    if (a > b) return a; else return b;}long long gf(long long x){    return ((fa[x] == x)?(x):(fa[x] = gf(fa[x])));}int main(){    freopen("doll.in","r",stdin);    freopen("doll.out","w",stdout);    //scanf("%lld", &n);    read(n);    for (long long i = 1;i <= n;i ++)    {        read(a[i].o),read(a[i].i),read(a[i].b);        //scanf("%lld%lld%lld", &a[i].o, &a[i].i, &a[i].b);        mxnm = max(mxnm,a[i].o);        ans += a[i].i * a[i].b;    }    sort(a + 1,a + 1 + n,cmpb);    for (long long i = 1;i <= n;i ++) t[a[i].o] ++;    for (long long i = 1;i <= mxnm;i ++)     {        fa[i] = i;        while (t[fa[i]] == 0 && fa[i] != 0) fa[i] = gf(-- fa[fa[i]]);    }    for (long long i = 1;i <= n;i ++)    {        long long l = gf(a[i].i - 1);           if (l > 0)        {            -- t[l];             ans -= l * a[i].b;            while (t[fa[l]] == 0 && fa[l] != 0) fa[l] = gf(-- fa[fa[l]]);           }    }    printf("%lld", ans);}
1 0