您的位置:首页 > 其它

NOIP2015普及组第四题解题报告

2015-11-14 14:33 441 查看
注意:本博客用于求助大神以及分享看到的好题解,求别喷

X=x时的最优解集合为U(x), last(U)为U中s最大的元素

v∈U(n)-U(x-1)且满足∀u∈U(n)-U(x-1)-{v}, s[v]+a[v]≥s[u]+a[u], U(x)=U(x-1)∪{v}

ans+=s[v]+a[v], 输出

若v>last(U(x-1)), 则∀u∈U(n)-U(x):

s[u]改为0 | u<v
s[u]减去s[v]-s[last(U(x-1))] | u>v

++x, 若x>n结束, 否则跳至1

//还是看代码吧

贪心的最优性证明(瞎写, 请喷):

假设U(x)不是最优解, 即∃u∈U(n)-U(x),∃v∈U(x)使U'(x)=U(x)∪{u}-{v}优于U(x)

设r=last(U(x)), 由假设, 有s[r]+a[r],s[v]+a[v]≥s[u]+a[u], v≤r

选择顺序为r→v

s[u]+a[u]>s[v]+a[v], 矛盾

选择顺序为v→r

有s[v]+a[v]≥s[r]+a[r]

u<v a[u]>a[v]≥s[r]+a[r]-s[v]≥s[r]+a[r]-s[u]

a[u]+s[u]>a[r]+s[r], 矛盾

v<u<r a[u]+s[u]>a[v]+s[v], 矛盾

r<u a[u]>a[v]≥s[r]+a[r]-s[v]

a[u]+s[u]>s[r]+a[r]+s[u]-s[v]≥s[r]+a[r], 矛盾

综上, U(x)为最优解

//这个是priority_queue+O(n)预处理suffix维护最值.场上写的是segment tree维护最值, 100+行

贪心
X=x时的最优解集合为U(x), last(U)为U中s最大的元素
1.
v∈U(n)-U(x-1)且满足∀u∈U(n)-U(x-1)-{v}, s[v]+a[v]≥s[u]+a[u], U(x)=U(x-1)∪{v}

2.
ans+=s[v]+a[v], 输出

3.
若v>last(U(x-1)), 则∀u∈U(n)-U(x):
1.s[u]改为0 | u<v
2.s[u]减去s[v]-s[last(U(x-1))] | u>v

4.
++x, 若x>n结束, 否则跳至1

//还是看代码吧

贪心的最优性证明(瞎写, 请喷):
假设U(x)不是最优解, 即∃u∈U(n)-U(x),∃v∈U(x)使U'(x)=U(x)∪{u}-{v}优于U(x)
设r=last(U(x)), 由假设, 有s[r]+a[r],s[v]+a[v]≥s[u]+a[u], v≤r
1.
选择顺序为r→v
s[u]+a[u]>s[v]+a[v], 矛盾

2.
选择顺序为v→r
有s[v]+a[v]≥s[r]+a[r]
1.
u<v a[u]>a[v]≥s[r]+a[r]-s[v]≥s[r]+a[r]-s[u]
a[u]+s[u]>a[r]+s[r], 矛盾

2.
v<u<r a[u]+s[u]>a[v]+s[v], 矛盾

3.
r<u a[u]>a[v]≥s[r]+a[r]-s[v]
a[u]+s[u]>s[r]+a[r]+s[u]-s[v]≥s[r]+a[r], 矛盾

综上, U(x)为最优解
//这个是priority_queue+O(n)预处理suffix维护最值.场上写的是segment tree维护最值, 100+行
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <queue>
#define rep(i,x,y) for (int i=x; i<=y; ++i)
#define repd(i,x,y) for (int i=x; i>=y; --i)

using namespace std;
const int N=100010;
char ch;
int ret,n,s
,a
,suf
,sp
,fst=1,ans,mxs;
priority_queue<int> h;

inline int getint()
{
while (!isdigit(ch=getchar()));
for (ret=ch-48; isdigit(ch=getchar()); ret=(ret<<3)+(ret<<1)+ch-48);
return ret;
}

int main()
{
n=getint();
rep(i,1,n)
s[i]=getint()<<1;
rep(i,1,n)
a[i]=getint();
repd(i,n,1)
if (suf[i+1]>s[i]+a[i])
suf[i]=suf[i+1],sp[i]=sp[i+1];
else
suf[i]=s[i]+a[i],sp[i]=i;
rep(i,1,n)
if (h.empty() || h.top()<suf[fst]-mxs)
{
printf("%d\n",ans+=suf[fst]-mxs);
rep(i,fst,sp[fst]-1)
h.push(a[i]);
fst=sp[fst]+1,mxs=s[fst-1];
}
else
printf("%d\n",ans+=h.top()),h.pop();
return 0;
}


P.S.这道题表示实在不懂,有更详细的题解请回复我


围观写出上面代码的人https://vijos.org/p/1977/solution

做出来在这里评测
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: