您的位置:首页 > 其它

1926: [Sdoi2010]粟粟的书架|主席树|二分答案

2016-03-14 19:14 375 查看
ym_fqk神犇提供做法

一边看AlphaGo VS 李世石一边写这个sb题居然1A辣。

做法显然。n=1时就是序列上主席树然后二分答案,否则就是区间维护1000个前缀和暴力再二分答案。最后要暴力一下最小值的出现次数。

暴力出奇迹,内存贴线过,差点被卡飞。。

#include<set>
#include<map>
#include<ctime>
#include<queue>
#include<cmath>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
int sc()
{
int i=0; char c=getchar();
while(c>'9'||c<'0')c=getchar();
while(c>='0'&&c<='9')i=i*10+c-'0',c=getchar();
return i;
}
int sum[1005][205][205],s[1005][205][205];
int a[205][205],b[500005],root[500005];
int t[8000008],sm[8000008],ch[8000008][2];
int n,m,Q,cnt;
int SUM(int d,int x1,int y1,int x2,int y2)
{
return sum[d][x2][y2]-sum[d][x1-1][y2]-sum[d][x2][y1-1]+sum[d][x1-1][y1-1];
}
void insert(int pre,int &x,int l,int r,int v)
{
if(!x)x=++cnt;
sm[x]=sm[pre]+v;t[x]=t[pre]+1;
if(l==r)return;
int mid=l+r>>1;
if(v<=mid)
ch[x][1]=ch[pre][1],
insert(ch[pre][0],ch[x][0],l,mid,v);
else
ch[x][0]=ch[pre][0],
insert(ch[pre][1],ch[x][1],mid+1,r,v);
}
int query(int L,int R,int H)
{
if(sm[R]-sm[L]<H)return 0;
int l=1,r=1000,tot=0;
while(l!=r)
{
int mid=l+r>>1;
int re=t[ch[R][1]]-t[ch[L][1]];
int res=sm[ch[R][1]]-sm[ch[L][1]];
if(res>=H)
L=ch[L][1],R=ch[R][1],l=mid+1;
else L=ch[L][0],R=ch[R][0],r=mid,H-=res,tot+=re;
}
tot+=t[R]-t[L];
int ans=sm[R]-sm[L];
while(ans-l>=H)ans-=l,tot--;
return tot;
}
void solve1()
{
for(int i=1;i<=m;i++)
b[i]=sc(),insert(root[i-1],root[i],1,1000,b[i]);
while(Q--)
{
int x1=sc(),l=sc(),x2=sc(),r=sc(),H=sc();
int ans=query(root[l-1],root[r],H);
if(!ans) puts("Poor QLW");
else printf("%d\n",ans);
}
}
void solve2()
{
int mx=0;
for(int i=1;i<=n;i++)
for(int j=1;j<=m;j++)
mx=max(mx,a[i][j]=sc());
for(int i=1;i<=mx;i++)
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
{
sum[i][j][k]=sum[i][j-1][k]+sum[i][j][k-1]-sum[i][j-1][k-1];
s[i][j][k]=s[i][j-1][k]+s[i][j][k-1]-s[i][j-1][k-1];
if(a[j][k]==i)sum[i][j][k]+=i,s[i][j][k]++;
}
for(int i=mx-1;i;i--)
for(int j=1;j<=n;j++)
for(int k=1;k<=m;k++)
s[i][j][k]+=s[i+1][j][k],
sum[i][j][k]+=sum[i+1][j][k];
while(Q--)
{
int x1=sc(),y1=sc(),x2=sc(),y2=sc(),H=sc();
int l=1,r=mx,ans=0;
while(l<=r)
{
int mid=l+r>>1;
int res=SUM(mid,x1,y1,x2,y2);
if(res>=H)ans=mid,l=mid+1;else r=mid-1;
}
if(ans)
{
int res=SUM(ans,x1,y1,x2,y2);
int tot=s[ans][x2][y2]-s[ans][x1-1][y2]-s[ans][x2][y1-1]+s[ans][x1-1][y1-1];
while(res-ans>=H)res-=ans,tot--;
printf("%d\n",tot);
}else puts("Poor QLW");
}
}
int main()
{
n=sc(),m=sc(),Q=sc();
if(n==1)solve1();else solve2();
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: