HDU_6047
题目意思
给你两个含有n个整数的序列a,b,其下标从1到n,现在要求满足 a[i]≤max{a[j]-j│b[k] ≤ j < i} 这个关系式的a[n+1]到a[2n],其中bk是从序列b中任意选取的,且b中的每个数只能使用一次。现在后要求a[n+1]到a[2n]的和,并使最后的和最大。
解题思路
由关系式可以知道a[i]{ i | n < i ≤ 2n }的值为a[b[k]]-b[k]到a[i-1]-(i-1)的最大值,所以b的值直接按照从小到大的顺序使用就可以了,可以用线段树来做,也可以直接循环嵌套来做
代码部分
用线段树做来写
#include <iostream>
#include <stdio.h>
#include <algorithm>
#define lchild left,mid,root<<1
#define rchild mid+1,right,root<<1|1
#define inf 0x3f3f3f3f
using namespace std ;
const int maxn = 600000 ;
const int mod = 1e9 +7 ;
int Max[maxn<<2 ];
int a[maxn];
int b[maxn];
void push_up(int root)
{
Max[root] = max(Max[root<<1 ],Max[root<<1 |1 ]);
}
void build(int left,int right,int root)
{
if (left == right)
{
Max[root] = a[left];
return ;
}
int mid = (left+right)>>1 ;
build(lchild);
build(rchild);
push_up(root);
}
int query(int L,int R,int left,int right,int root)
{
if (L<=left && right<=R)
return Max[root];
int mid = (left+right)>>1 ;
int ans = -inf;
if (L<=mid) ans = max(ans,query(L,R,lchild));
if (R>mid) ans = max(ans,query(L,R,rchild));
return ans;
}
void Insert(int pos,int left,int right,int root)
{
if (left == right)
{
Max[root] = a[pos]-pos;
return ;
}
int mid = (left+right)>>1 ;
if (pos<=mid) Insert(pos,lchild);
else Insert(pos,rchild);
push_up(root);
}
int main()
{
int n;
while (~scanf ("%d" ,&n))
{
for (int i = 1 ; i <= n; i++)
{
scanf ("%d" ,&a[i]);
a[i] = a[i]-i;
}
for (int i = 1 ; i <= n; i++)
{
scanf ("%d" ,&b[i]);
a[i+n] = -inf;
}
sort(b,b+n);
build(1 ,2 *n,1 );
int ans = 0 ;
int range = n;
for (int i = 1 ; i <= n; i++)
{
int num = query(b[i],range,1 ,2 *n,1 );
range++;
a[i+n] = num;
Insert(n+i,1 ,2 *n,1 );
ans = (ans+num)%mod;
}
printf ("%d\n" ,ans);
}
return 0 ;
}
用循环套嵌来写
#include <iostream>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <algorithm>
#define MAXN 500050
#define ll long long
using namespace std;
const int MOD=1e9 +7 ;
int main()
{
int n;
ll d[MAXN];
while (~scanf("%d" ,&n))
{
ll a[MAXN];
int c,b[MAXN];
memset(d,0 ,sizeof (d));
a[0 ]=0 ;
b[0 ]=0 ;
for (int i=1 ; i<=n; i++)
{
scanf("%d" ,&c);
a[i]=c-i;
}
for (int i=1 ; i<=n; i++)
{
scanf("%d" ,&b[i]);
}
sort(b+1 ,b+n+1 );
int y=n,k=1 ,i=0 ,pos;
ll sum=0 ;
while (y<2 *n)
{
if (i>n&&a[i]<d[b[k-1 ]]&&b[k]<=pos)
d[b[k]]=d[b[k-1 ]];
else for (i=b[k]; i<=y; i++)
{
d[b[k]]=max(d[b[k]],a[i]);
if (d[b[k]]==a[i])pos=i;
}
i=y+1 ;
a[i]=d[b[k]]-i;
sum=(sum+d[b[k]])%MOD;
k++;
y++;
}
printf("%lld\n" ,sum);
}
}