1926: [Sdoi2010]粟粟的书架|主席树|二分答案
2016-03-14 19:14
375 查看
ym_fqk神犇提供做法
一边看AlphaGo VS 李世石一边写这个sb题居然1A辣。
做法显然。n=1时就是序列上主席树然后二分答案,否则就是区间维护1000个前缀和暴力再二分答案。最后要暴力一下最小值的出现次数。
暴力出奇迹,内存贴线过,差点被卡飞。。
一边看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; }
相关文章推荐
- Round #292 (Div. 2)
- 如果让我回到大一!!!
- 安卓我的课表
- 观察者(Observer)模式
- 构建Mysql连接池
- com.android.volley 里面网络请求的使用
- PowerPoint出现“受保护的视图,Office已检测到该文件存在问题。编辑此文件可能会损坏您的计算机。”的提示
- svn的安装和服务器搭建, 汉化以及多项目管理
- 未找到arm-linux-gcc解决办法
- SQL 语句之insert语句插入数据;若表中有重复的主键或数据插入的时候要求不能报错
- 二叉树的前/中/后序遍历
- Qt信号和槽问题
- Android 中 Activity的生命周期简单描述(新手)
- bzoj3192: [JLOI2013]删除物品
- "_OBJC_CLASS_$_LLWalletSdk", referenced from: 的解决方法
- 十六进制到10进制转换
- QT中qmlRegisterType qmlRegisterSingletonType的区别
- 关于textView实时监控输入文字长度
- pdf word在线转换器
- BZOJ4399: 魔法少女LJJ