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);
}
}