题目链接:
http://codeforces.com/problemset/problem/581/B
题目大意:
给n个不同高度的房子,要求当对于第i个房子来说,他要严格的比后面的房子都高。
思路:
题目意思读懂以后,很容易想到,对于第i个房子,我只要找到(i+1,n)的最大值M,然后第i个房子值变为M+1即可。
所以就是简单的点更新,区间查询。
代码:
#include<stdio.h>
#include<string.h>
#define ll __int64
#define M 100005
ll max(ll a,ll b)
{
if(a>b)return a;
else return b;
}
struct tree{
ll l,r,sum;
}tree[M<<2];
void build(ll l,ll r,ll root)
{
tree[root].l=l;
tree[root].r=r;
tree[root].sum=0;
if(l==r)return;
ll mid=l+r>>1;
build(l,mid,root<<1);
build(mid+1,r,root<<1|1);
}
void pushup(ll root)
{
if(tree[root].l==tree[root].r)return;
tree[root].sum=max(tree[root<<1].sum,tree[root<<1|1].sum);
}
void update(ll l,ll r,ll root,ll z)
{
if(tree[root].l==l&&tree[root].r==r)
{
tree[root].sum=z;
return;
}
ll mid=tree[root].l+tree[root].r>>1;
if(r<=mid)update(l,r,root<<1,z);
else if(l>mid)update(l,r,root<<1|1,z);
else {
update(l,mid,root<<1,z);
update(mid+1,r,root<<1|1,z);
}
pushup(root);
}
ll query(ll l,ll r,ll root)
{
if(tree[root].l==l&&tree[root].r==r)
{
return tree[root].sum;
}
ll mid=tree[root].l+tree[root].r>>1;
if(r<=mid)return query(l,r,root<<1);
else if(l>mid)return query(l,r,root<<1|1);
else return max(query(l,mid,root<<1),query(mid+1,r,root<<1|1));
}
int main()
{
ll n,i,j,k,b[100005],a[100005];
while(scanf("%I64d",&n)!=EOF)
{
build(1,n,1);
memset(b,0,sizeof(b));
memset(a,0,sizeof(a));
for(i=1;i<=n;i++)
{
scanf("%I64d",&a[i]);
update(i,i,1,a[i]);
}
ll f=0;
b[n]=0;
for(i=1;i<=n-1;i++)
{
ll maxi=query(i+1,n,1);
b[i]=maxi+1-a[i];
if(b[i]<0)b[i]=0; //可能会出现负数,其实就是不需要增加高度。
}
for(i=1;i<n;i++)
printf("%I64d ",b[i]);
printf("%I64d\n",b[n]);
}
}
可以这么看:我从右向左看,对于当前第i个来说,我只要看(i+1,n)的最大值是否大于他自己,如果是:就是maxi-a[i]+1,表示我需要加上这些才能比后面的最大的大。否则就是他自己是当前最大的,就是0了。
其实跟上面的线段树一模一样。。但是就不用每次都去查询区间最大值了。
代码:
#include<stdio.h>
#include<string.h>
#define ll __int64
ll max(ll a,ll b)
{
if(a>b)return a;
else return b;
}
int main()
{
ll n,a[100005],b[100005],maxi,i,j;
while(scanf("%I64d",&n)!=EOF)
{
memset(a,0,sizeof(a));
memset(b,0,sizeof(b));
for(i=1;i<=n;i++)
scanf("%I64d",&a[i]);
maxi=a[n];
b[n]=0;
for(i=n-1;i>=1;i--)
{
if(a[i]<=maxi)
{
b[i]=maxi-a[i]+1;
}
else if(a[i]>maxi)b[i]=0;
if(maxi<a[i])maxi=a[i];
}
for(i=1;i<n;i++)
printf("%I64d ",b[i]);
printf("%I64d\n",b[n]);
}
}