hdu 3884 Hinanai Tenshi’s peach garden
http://acm.hdu.edu.cn/showproblem.php?pid=3884
二分+验证
验证是否可以把t个桃子放在同一点的时候,
这t个桃子必然是连续的,假设存在于区间[a,b]
这个区间的两个端点必然有一个是满的(所以扫描的时候左右扫两遍)
先假设a点是满的
那么找第t个桃子所在的位置
再找中间第(t+1)/2 个桃子的位置 (距离和最小)
此时得到中间位置,左右两边的位置,就可以验证是否超出花费了。
注:当t是偶数的时候,中间的桃子应该是有两个的,我考虑之后就TLE了,因为我的算法复杂度是 O(lgm*n*lgn*lgn) (m是桃子总数,n是位置数)
后来统一考虑中间的那个桃子就是第(t+1)/2个,就900多ms过了==!
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <string.h>
#include <cmath>
#include <vector>
using namespace std;
__int64 N,K;
const int maxn = 10005;
struct node
{
__int64 x;
__int64 p;
}a[maxn];
__int64 lb[maxn];
__int64 lc[maxn];
__int64 rb[maxn];
__int64 rc[maxn];
void solve()
{
lb[0]=0,lc[0]=0;
for(int i=1;i<=N;i++)
{
lb[i]=lb[i-1]+a[i].p;
lc[i]=lc[i-1]+a[i].p*a[i].x;
}
rb[N+1]=0,rc[N+1]=0;
for(int i=N;i>=1;i--)
{
rb[i]=rb[i+1]+a[i].p;
rc[i]=rc[i+1]+a[i].p*a[i].x;
}
}
int Find_left(int pur,int l,int r,__int64 v)
{
int ans=N+1;
while(l<=r)
{
int mid=(l+r)/2;
if(lb[mid]-lb[pur-1]==v)
return mid;
else if(lb[mid]-lb[pur-1]<v)
l=mid+1;
else
{
if(mid<ans)
ans=mid;
r=mid-1;
}
}
if(ans==N+1)
return -1;
return ans;
}
int Find_right(int pur,int l,int r,__int64 v)
{
int ans=0;
while(l<=r)
{
int mid=(l+r)/2;
if(rb[mid]-rb[pur+1]==v)
return mid;
else if(rb[mid]-rb[pur+1]<v)
r=mid-1;
else
{
if(mid>ans)
ans=mid;
l=mid+1;
}
}
if(ans==0)
return -1;
return ans;
}
bool Is_true(__int64 t) //验证是否可以放t个桃子到同一个点
{
int l=0,r=0,mid=0;
__int64 suk=0;
for(int i=1;i<=N;i++)
{
suk=0;
l=i;
r=Find_left(i,i,N,t);
if(r==-1)
continue;
mid=Find_left(i,i,N,(t+1)/2);
suk+=a[mid].x*(lb[mid-1]-lb[l-1])-(lc[mid-1]-lc[l-1]);
suk+=lc[r-1]-lc[mid]-a[mid].x*(lb[r-1]-lb[mid]);
suk+= (a[r].p-(lb[r]-lb[l-1]-t))*(a[r].x-a[mid].x);
if(suk<=K)
return true;
/* if(t%2==0)
{
suk=0;
mid=Find_left(i,i,N,(t+2)/2);
suk+=a[mid].x*(lb[mid-1]-lb[l-1])-(lc[mid-1]-lc[l-1]);
suk+=lc[r-1]-lc[mid]-a[mid].x*(lb[r-1]-lb[mid]);
suk+= (a[r].p-(lb[r]-lb[l-1]-t))*(a[r].x-a[mid].x);
if(suk<=K)
return true;
}*/
}
for(int i=N;i>=1;i--)
{
suk=0;
r=i;
l=Find_right(i,1,i,t);
if(l==-1)
continue;
mid=Find_right(i,1,i,(t+1)/2);
suk+=rc[mid+1]-rc[i+1]-a[mid].x*(rb[mid+1]-rb[i+1]);
suk+=a[mid].x*(rb[l+1]-rb[mid])-(rc[l+1]-rc[mid]);
suk+=(a[l].p-(rb[l]-rb[r+1]-t))*(a[mid].x-a[l].x);
if(suk<=K)
return true;
/* if(t%2==0)
{
suk=0;
mid=Find_right(i,1,i,(t+2)/2);
suk+=rc[mid+1]-rc[i+1]-a[mid].x*(rb[mid+1]-rb[i+1]);
suk+=a[mid].x*(rb[l+1]-rb[mid])-(rc[l+1]-rc[mid]);
suk+=(a[l].p-(rb[l]-rb[r+1]-t))*(a[mid].x-a[l].x);
if(suk<=K)
return true;
}*/
}
return false;
}
int cmp(node a1,node a2)
{
return a1.x<a2.x;
}
int main()
{
__int64 sum=0;
while(scanf("%I64d %I64d",&N,&K)!=EOF)
{
sum=0;
for(int i=1;i<=N;i++)
{
scanf("%I64d %I64d",&a[i].x,&a[i].p);
sum+=a[i].p;
}
sort(a+1,a+N+1,cmp);
solve();
__int64 l=0;
__int64 r=sum;
__int64 ans=0;
while(l<=r)
{
__int64 mid=(l+r)/2;
if(Is_true(mid)==true)
{
if(ans<mid)
ans=mid;
l=mid+1;
}
else
r=mid-1;
}
printf("%I64d\n",ans);
}
return 0;
}
浙公网安备 33010602011771号