写了个做法 86pts TLE。思路大概类似单调栈(?)。就是说你前面的人比你高,你就不可能吃到任何东西,因为你前面的人身高是单调不减的,你能吃到的他都能吃到。于是就可以把这头奶牛删去再进行下一个操作。代码就是用双向链表实现删除。求复杂度为什么假了。
#include <iostream>
#include <cstdio>
using namespace std;
typedef long long LL;
const LL MAXN = 200005;
struct Node
{
LL id, pre, nex, heig;
bool flag;
} Lis[MAXN];
LL n, m, tot = 0, head = 1;
LL A[MAXN], ans[MAXN];
void Add(LL id, LL heig)
{
tot ++;
Lis[tot].pre = tot - 1;
Lis[tot - 1].nex = tot;
Lis[tot].id = id;
Lis[tot].heig = heig;
Lis[tot].flag = false;
return;
}
void Dele(LL id)
{
Lis[Lis[id].pre].nex = Lis[Lis[id].nex].id;
Lis[Lis[id].nex].pre = Lis[Lis[id].pre].id;
Lis[id].flag = true;
while(Lis[head].flag && head <= n) head ++;
return;
}
int main()
{
scanf("%lld%lld", &n, &m);
LL tmp;
Lis[0].heig = 0;
Lis[n + 1].heig = 0;
for(LL i = 1; i <= n; i ++)
{
scanf("%lld", &tmp);
Add(i, tmp);
}
for(LL i = 1; i <= m; i ++) scanf("%lld", &A[i]);
LL nowbottom = 1;
for(LL i = 1; i <= m; i ++)
{
// cout << head << endl;
LL cur = head;
do
{
// cout << cur << " " << Lis[cur].pre << endl;
if(Lis[cur].heig <= Lis[Lis[cur].pre].heig)
{
// cout << Lis[cur].heig << " " << Lis[Lis[cur].pre].heig << endl;
Dele(cur);
ans[Lis[cur].id] = Lis[cur].heig;
cur = Lis[Lis[cur].pre].nex;
}
else cur = Lis[cur].nex;
} while(cur);
nowbottom = 1;
cur = head;
do
{
if(Lis[cur].heig >= nowbottom)
{
LL nt = nowbottom;
nowbottom = min(A[i], Lis[cur].heig) + 1;
Lis[cur].heig += min(A[i], Lis[cur].heig) - nt + 1;
}
cur = Lis[cur].nex;
} while(cur && nowbottom <= A[i]);
}
LL cur = head;
do
{
ans[Lis[cur].id] = Lis[cur].heig;
cur = Lis[cur].nex;
} while(cur);
for(LL i = 1; i <= n; i ++) printf("%lld\n", ans[i]);
return 0;
}