hdu 3486 RMQ + 二分

二分一个分段数,再用RMQ累加区间最值,跑的好慢哦
 
#include<stdio.h>
#include<string.h>
const int MAX = 200010;
#define min(a,b) a<b?a:b
#define max(a,b) a>b?a:b
int dp[MAX][30],a[MAX];
int k;
void init(int n)
{
    memset(dp,0,sizeof(dp));
	int i,j,m;
	for(i=1;i<=n;i++)
	{
		dp[i][0]=a[i];
	}
	for(j=1,m=1;m<=n;m<<=1,j++)
		for(i=n;i>=1;i--)
		{
			if(i+(1<<(j-1))<=n)
				dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
		}
}
int RMQ(int l,int r)
{
	int i,j,k,a;
	k=r-l+1;
	for(i=0,j=1;j<=k;j<<=1,i++)
	{
		a=max(dp[l][i],dp[r-j+1][i]);
	}
	return a;
}
int getmax(int per,int mid)
{
     int i;
	 int ans=0;
	 for(i=1;i<=mid;i++)
	 {
		 ans+=RMQ((i-1)*per+1,i*per);
		 if(ans>k) return ans;
	 }
	 return 0;
}
int main()
{
	int n,i;
	while(scanf("%d%d",&n,&k),n>0)
	{
		int sum=0;
		int num=0;
		for(i=1;i<=n;i++)
        {
			scanf("%d",&a[i]);
			if(a[i]>num) num=a[i];
			sum+=a[i];
		}
		if(num>k){ printf("1\n");continue;}
		if(sum<=k)
		{printf("-1\n");continue;}
		init(n);
	//	printf("%d %d\n",RMQ(1,3),RMQ(9,8));check RMQ
		int  l=1,r=n,mid;
		int ans=0;
		while(l<=r)
		{
            mid=(l+r)>>1;
            int per=n/mid;
			int tmp=getmax(per,mid);
			if(tmp>k)
			{
				r=mid-1;
				ans=mid;
			}
		    else l=mid+1;
		}
		printf("%d\n",ans);
	}
	return 0;
}


 

RMQ写法换了,93ms!!!

#include<string.h>
#include<stdio.h>
#include<math.h>
const int MAX=200005;
int max(int a,int b){return a>b?a:b;}
int dp[MAX][20],a[MAX];
int n,k,val[MAX];
int  LOG[MAX];
void Make_Rmq(int n,int b[])
{
 int i,j;
 for(i=1;i<=n;i++)
  dp[0][i]=b[i];
 for(i=1;i<=LOG[n];i++)
 {
  int limit=n+1-(1<<i);
  for(j=1;j<=limit;j++)
   dp[i][j]=max(dp[i-1][j],dp[i-1][j+(1<<i>>1)]);
 }
}
int RMQ(int l,int r)
{
 int  k=LOG[r-l+1];
 return max(dp[k][l],dp[k][r-(1<<k)+1]);
}
int getmax(int per,int mid)
{
 int i;
 int ans=0;
 for(i=1;i<=mid;i++)
 {
  ans+=RMQ((i-1)*per+1,i*per);
  if(ans>k) return ans;
 }
 return 0;
}
int get_val()
{    
 int ret(0);    
 char c;    
 while((c=getchar())==' '||c=='\n'||c=='\r');    
 ret=c-'0';    
 while((c=getchar())!=' '&&c!='\n'&&c!='\r')                
  ret=ret*10+c-'0';    
 return ret;
}
int main()
{
 int i;
 LOG[0]=-1;
 for(i=1;i<MAX;i++)
  LOG[i]=LOG[i>>1]+1;
 while(scanf("%d%d",&n,&k),n>0)
 {
  int sum=0;
  int num=0;
  for(i=1;i<=n;i++)
  {
   // scanf("%d",&val[i]);
   val[i]=get_val();
   if(val[i]>num) num=val[i];
   sum+=val[i];
  }
  if(num>k){ printf("1\n");continue;}
  if(sum<=k)
  {printf("-1\n");continue;}
  Make_Rmq(n,val);
  int  l=1,r=n,mid;
  int ans=0;
  while(l<=r)
  {
   mid=(l+r)>>1;
   int per=n/mid;
   int tmp=getmax(per,mid);
   if(tmp>k)
   {
    r=mid-1;
    ans=mid;
   }
   else l=mid+1;
  }
  printf("%d\n",ans);
 }
 return 0;
}

 

posted @ 2011-10-24 18:54  Because Of You  Views(724)  Comments(0Edit  收藏  举报