首页 > 学院 > 开发设计 > 正文

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

2019-11-08 18:33:09
字体:
来源:转载
供稿:网友

传送门

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 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);}
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表