好坑的一道题目!
看到题面,再看看 “In tests worth 50% of the points the condition n<=1000 holds in addition.” , 很容易把人往dp优化之类的地方想。
然后就会杯具了。。。。跳出dp吧!
把两个数列分别做个前缀和,任务很明显,在b数组中删除一些数,使得前缀和数组中每个i,sumai>=sumbi
注意到每次删除bi有影响的只有区间[i,n],由此我们可以贪心了。
从前向后扫描,如果此处还不满足sumai>=sumbi,只需在[1,i]中找到未被删除的最大的bj,删除,直到满足sumai>=sumbi
找最大值可以用对实现。注意到被删的数字最前缀和后不减,那么直接用变量表示被删了多少数 而不用线段树赋值。
具体实现见程序吧~~~~
#include <queue> #include <cstdio> #include <cstring> #include <algorithm> using namespace std; typedef long long LL; const int Maxn=300005; LL a[Maxn],b[Maxn],suma[Maxn],sumb[Maxn],dt; int i,n,ans,p[Maxn]; bool v[Maxn]; struct arr { int x; bool operator <(const arr &a)const { return b[x]<b[a.x]; } } tmp; priority_queue <arr> heap; int main(){ freopen("hur.in","r",stdin); freopen("hur.out","w",stdout); scanf("%d",&n); for (i=1;i<=n;i++) scanf("%I64d",&a[i]); for (i=1;i<=n;i++) scanf("%I64d",&b[i]); for (i=1;i<=n;i++){ suma[i]=suma[i-1]+a[i]; sumb[i]=sumb[i-1]+b[i]; } for (i=1,dt=0;i<=n;i++){ heap.push((arr){i}); while (sumb[i]-suma[i]>dt){ tmp=heap.top(); heap.pop(); dt+=b[tmp.x]; v[tmp.x]=1; } } for (i=1;i<=n;i++) if (!v[i]) p[++ans]=i; printf("%d\n",ans); if (ans==0) return 0; for (i=1;i<ans;i++) printf("%d ",p[i]); printf("%d\n",p[ans]); return 0; }