解题思路:这是一个模拟题目。
题目要求找到货物i所在的区间,将货物取出,同时区间一分为二。要求输出每次拿完货物之后货物和最大的区间。读者如果之间做过区间排序、区间查找、区间合并类题目对这类问题会有更好的思路。
模拟一下,初始区间为(1,n),拿走第i元素后(1,i-1),(i+1,n),显然每次拿走一个货物,区间数量或者多一个,或者数量不变(拿走区间端点)。因此可以用结构体描述区间,按区间右端点进行排序。这样能快速找到i所在区间。找到后将其删除,再将结果(两个分割后区间)放入。涉及删除插入,所以应用动态查找表存储区间。本题目用set存储区间。
最大值怎么办,用另一个动态查找结构存储区间对应的和值,当我们找到区间(x,y)将其分割后,同时也在另一个结构中拿出它的和值进行分割。因区间的和值可能有重复,所以用multiset存储。
#include <bits/stdc++.h>
typedef long long ll;
using namespace std;
struct node
{
int l,r;
bool operator<(const node Y)const
{ /**< 以区间右端点排序 */
return r<Y.r;
}
};
set<node>st;
multiset<int>s;
int n,a[50005],sum[50005];
int main()
{
ios::sync_with_stdio(0),cin.tie(0);
int i,j,x;
cin>>n;
for(i=1; i<=n; i++)
cin>>a[i],sum[i]=sum[i-1]+a[i];
st.insert({1,n}); //st存储区间,s存储和值
s.insert(sum[n]);
s.insert(0);
for(i=1; i<=n; i++)
{
cin>>x;
node t=*(st.lower_bound({x,x}));/**< 找到x对应区间 */
int l=t.l,r=t.r;
st.erase(t);
if(l<x) /**< 替换为[L,X-1],[X+1,R] */
st.insert({l,x-1});
if(r>x)
st.insert({x+1,r});
multiset<int>::iterator it=s.lower_bound(sum[r]-sum[l-1]);
s.erase(it);/**< 找到对应子段和,并删除 */
if(l<x) /**< 插入[L,X-1],[X+1,R]的子段和 */
s.insert(sum[x-1]-sum[l-1]);
if(r>x)
s.insert(sum[r]-sum[x]);
it=s.end();/**< 用迭代器找到最后一个点的指针 */
it--; /**< end是最后一个点后一个,所以自减,亦可以定义反向迭代器 */
cout<<*(it)<<endl;
}
return 0;
}