您的位置:首页 > 其它

bzoj 1926: [Sdoi2010]粟粟的书架

2016-03-18 05:54 525 查看
#include<cstdio>
#include<iostream>
#define N 201
#define M 500008
using namespace std;
int cnt,r,c,m,ls[20*M],rs[20*M],root[M],ans,sum[20*M],sum1[20*M],shu,num[1008]

,num1[1008]

;
void jia(int l,int r,int x,int &y,int v)
{
y=++cnt;
sum[y]=sum[x]+v;
sum1[y]=sum1[x]+1;
if(l==r)
return;
ls[y]=ls[x];
rs[y]=rs[x];
int mid=(l+r)>>1;
if(v<=mid)
jia(l,mid,ls[x],ls[y],v);
else
jia(mid+1,r,rs[x],rs[y],v);
return;
}
int xun(int a1,int a2,int l,int r,int v)
{
if(!a1)
return 0;
if(l>=v)
{
shu-=sum[a1]-sum[a2];
return sum1[a1]-sum1[a2];
}
int s=0,mid=(l+r)>>1;
if(mid>=v)
s+=xun(ls[a1],ls[a2],l,mid,v);
s+=xun(rs[a1],rs[a2],mid+1,r,v);
return s;
}
void solve1()
{
for(int i=1;i<=c;i++)
{
int a1;
scanf("%d",&a1);
jia(1,1000,root[i-1],root[i],a1);
}
for(int i=1;i<=m;i++)
{
int x0,y0,x1,y1,v;
scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&v);
int l=0,r=1000,mid=(l+r)>>1,b1,md,md1;
ans=0;
for(;l<=r;)
{
shu=v;
b1=xun(root[y1],root[y0-1],1,1000,mid);
if(shu<=0)
{
md1=v-shu;
md=mid;
ans=b1;
l=mid+1;
}
else
r=mid-1;
mid=(l+r)>>1;
}
if(!ans)
printf("Poor QLW\n");
else
{
int a1;
r=xun(root[y1],root[y0-1],1,1000,md+1);
r=ans-r;
l=0;
mid=(l+r)>>1;
for(;l<=r;)
{
if(md1-mid*md>=v)
{
a1=ans-mid;
l=mid+1;
}
else
r=mid-1;
mid=(l+r)>>1;
}
printf("%d\n",a1);
}
}
return;
}
void solve2()
{
for(int i=1;i<=r;i++)
for(int j=1;j<=c;j++)
{
int a1;
scanf("%d",&a1);
for(int k=0;k<=1000;k++)
{
num[k][i][j]=(num[k][i][j-1]+num[k][i-1][j]-num[k][i-1][j-1]);
num1[k][i][j]=(num1[k][i][j-1]+num1[k][i-1][j]-num1[k][i-1][j-1]);
if(a1>=k)
{
num[k][i][j]+=a1;
num1[k][i][j]++;
}
}
}
for(int i=1;i<=m;i++)
{
int x0,y0,x1,y1,v;
scanf("%d%d%d%d%d",&x0,&y0,&x1,&y1,&v);
int l=0,r=1000,mid=(l+r)>>1,tm=0,tm1=0,tm2=0;
for(;l<=r;)
{
if(num[mid][x1][y1]-num[mid][x1][y0-1]-num[mid][x0-1][y1]+num[mid][x0-1][y0-1]>=v)
{
tm=num1[mid][x1][y1]-num1[mid][x1][y0-1]-num1[mid][x0-1][y1]+num1[mid][x0-1][y0-1];
tm1=mid;
l=mid+1;
}
else
r=mid-1;
mid=(l+r)>>1;
}
if(!tm)
printf("Poor QLW\n");
else
{
tm2=num[tm1][x1][y1]-num[tm1][x1][y0-1]-num[tm1][x0-1][y1]+num[tm1][x0-1][y0-1];
l=0,r=num1[tm1+1][x1][y1]-num1[tm1+1][x1][y0-1]-num1[tm1+1][x0-1][y1]+num1[tm1+1][x0-1][y0-1];
r=tm-r;
mid=(l+r)>>1;
for(;l<=r;)
{
if(tm2-mid*tm1>=v)
{
ans=tm-mid;
l=mid+1;
}
else
r=mid-1;
mid=(l+r)>>1;
}
printf("%d\n",ans);
}
}
return;
}
int main()
{
scanf("%d%d%d",&r,&c,&m);
if(r==1)
solve1();
else
solve2();
return 0;
}


两种情况 对于R,C<=200,用前缀和暴力二分,对于另外的数据,在主席树上二分。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: