您的位置:首页 > Web前端 > JavaScript

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

2017-02-16 19:55 288 查看
传送门

Analysis

直接考虑答案

Ans=∑Ii⋅Bi−∑Ai⋅Bi

其中Ai指i所匹配的out的大小。

显然,为使Ans最小,要使∑Ai⋅Bi尽量大。

剩下的,也就没什么了。

对于一个尽量大的Bi,选择一个尽量大的Oj

至于实现的话…别人都跟我说使用线段树。

但是我会O(n)[不包含排序],为什么要用O(n log n)

比如说,既然一个选择不会被其他的选择影响,那我们可以直接统排了Oi

剩下的自己YY,YY不出来看代码。

–思考时间–

Code

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define oo 2139062143
using namespace std;
const long long N = 200200, NUM = 10100;
long long n,ans;
struct node{
long long i,o,b;
}a
,b
;
long long t
,mxnm,fa
;
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);
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: