线段树套treap+dp(BZOJ1926)
来源:互联网 发布:站内搜索优化方案 编辑:程序博客网 时间:2024/06/07 15:27
1926: [Sdoi2010]粟粟的书架
Time Limit: 20 Sec Memory Limit: 552 MBSubmit: 482 Solved: 177
[Submit][Status]
Description
Input
第一行是三个正整数R, C, M。 接下来是一个 R行C 列的矩阵,从上到下、从左向右依次给出了每本书的页数Pi,j。 接下来 M行,第 i 行给出正整数x1i, y1i, x2i, y2i, Hi,表示第i 天的指定区域是﹙x1i, y1i﹚与﹙x2i, y2i﹚间的矩形,总页数之和要求不低于 Hi。 保证 1≤x1i≤x2i≤R,1≤y1i≤y2i≤C。
Output
有M行,第i 行回答粟粟在第 i 天时为摘到苹果至少需要拿取多少本书。如果即使取走所有书都无法摘到苹果,则在该行输出“Poor QLW”(不含引号)。
Sample Input
5 5 7
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108
14 15 9 26 53
58 9 7 9 32
38 46 26 43 38
32 7 9 50 28
8 41 9 7 17
1 2 5 3 139
3 1 5 5 399
3 3 4 5 91
4 1 4 1 33
1 3 5 4 185
3 3 4 3 23
3 1 3 3 108
Sample Output
6
15
2
Poor QLW
9
1
3
15
2
Poor QLW
9
1
3
HINT
对于 10%的数据,满足 R, C≤10;
对于 20%的数据,满足 R, C≤40;
对于 50%的数据,满足 R, C≤200,M≤200,000;
另有 50%的数据,满足 R=1,C≤500,000,M≤20,000;
对于 100%的数据,满足 1≤Pi,j≤1,000,1≤Hi≤2,000,000,000。
思路:分情况讨论,对于R!=1的来说,用dp递推一下就行了dp[i][j][k],表示坐标(0,0)到(i,j)页数为k的有多少本,查询的时候从最高页数开始暴力就行了
对于R==1的情况则要用树套树进行处理:首先二分页数,然后查询大于等于这个页数的总页数是多少
#include<iostream>#include<cstdio>#include<string>#include<cstring>#include<vector>#include<cmath>#include<queue>#include<stack>#include<map>#include<set>#include<algorithm>using namespace std;const int maxn=500010;int a[maxn];int R,C,M;int tot;int f[205][205][1005];struct Node{ int ch[2]; int r;//优先级 int v;//值 int s; int sum; int cnt;//自身重复次数 void init(int val){v=val;ch[0]=ch[1]=0;s=cnt=1;r=rand();sum=0;} int cmp(int x)const { if(x==v)return -1; return x<v?0:1; }}tree[maxn*20];void maintain(int x){ tree[x].s=tree[x].cnt; tree[x].s+=tree[tree[x].ch[0]].s+tree[tree[x].ch[1]].s; tree[x].sum=tree[x].cnt*tree[x].v+tree[tree[x].ch[0]].sum+tree[tree[x].ch[1]].sum;}void rotate(int &o,int d){ int k=tree[o].ch[d^1]; tree[o].ch[d^1]=tree[k].ch[d]; tree[k].ch[d]=o; maintain(o); maintain(k); o=k;}void insert(int &o,int x){ if(!o) { o=++tot; tree[o].init(x); } else { if(x==tree[o].v)tree[o].cnt++; else { int d=(x<tree[o].v?0:1); insert(tree[o].ch[d],x); if(tree[tree[o].ch[d]].r>tree[o].r) rotate(o,d^1); } } maintain(o);}void remove(int &o,int x){ if(!o)return; int d=tree[o].cmp(x); if(d==-1) { int u=o; if(tree[o].cnt>1)tree[o].cnt--; else if(tree[o].ch[0]&&tree[o].ch[1]) { int d2=(tree[tree[o].ch[0]].r>tree[tree[o].ch[1]].r?1:0); rotate(o,d2); remove(tree[o].ch[d2],x); } else { if(!tree[o].ch[0])o=tree[o].ch[1]; else o=tree[o].ch[0]; } } else remove(tree[o].ch[d],x); if(o)maintain(o);}//返回最大值int get_max(int o){ while(tree[o].ch[0])o=tree[o].ch[0]; return tree[o].v;}//返回最小值int get_min(int o){ while(tree[o].ch[1])o=tree[o].ch[1]; return tree[o].v;}//返回val的前驱,如果没有的话返回y//y的初值可赋成0,表示没有前驱int get_pred(int o,int val,int y){ if(!o)return y; if(tree[o].v<=val)//注意大于等于号 return get_pred(tree[o].ch[1],val,tree[o].v); else return get_pred(tree[o].ch[0],val,y);}//返回val的后继,如果没有的话返回y//y的初值可赋成0,表示没有后继int get_succ(int o,int val,int y){ if(!o)return y; if(tree[o].v>=val)return get_succ(tree[o].ch[0],val,tree[o].v); else return get_succ(tree[o].ch[1],val,y);}//返回第k大的元素的值int get_kth(int o,int k){ if(!o)return 0; if(k<=tree[tree[o].ch[0]].s)return get_kth(tree[o].ch[0],k); else if(k>tree[tree[o].ch[0]].s+tree[o].cnt) return get_kth(tree[o].ch[1],k-tree[tree[o].ch[0]].s-tree[o].cnt); return tree[o].v;}//返回val的排名int get_rank(int o,int val){ if(!o)return 0; int lsize=tree[tree[o].ch[0]].s; if(val<tree[o].v) return get_rank(tree[o].ch[0],val); else if(val>tree[o].v) return get_rank(tree[o].ch[1],val)+lsize+tree[o].cnt; return lsize+tree[o].cnt;}pair<int,int> getcnt(int o,int val){ if(!o)return make_pair(0,0); int lsize=tree[tree[o].ch[0]].s; if(val<tree[o].v) { pair<int,int> tmp=getcnt(tree[o].ch[0],val); tmp.first+=tree[o].cnt+tree[tree[o].ch[1]].s; tmp.second+=tree[tree[o].ch[1]].sum+tree[o].v*tree[o].cnt; return tmp; } else if(val>tree[o].v) return getcnt(tree[o].ch[1],val); int cnt=tree[tree[o].ch[1]].s+tree[o].cnt; int sum=tree[tree[o].ch[1]].sum+tree[o].v*tree[o].cnt; return make_pair(cnt,sum);}struct IntervalTree{ int root[maxn<<2]; void build(int o,int l,int r) { root[o]=0; for(int i=l;i<=r;i++)insert(root[o],a[i]); if(l==r)return; int mid=(l+r)>>1; build(o<<1,l,mid); build(o<<1|1,mid+1,r); } pair<int,int> query(int o,int l,int r,int q1,int q2,int val) { if(q1<=l&&r<=q2)return getcnt(root[o],val); int mid=(l+r)>>1; if(q2<=mid)return query(o<<1,l,mid,q1,q2,val); if(q1>mid)return query(o<<1|1,mid+1,r,q1,q2,val); pair<int,int> p,q; p=query(o<<1,l,mid,q1,mid,val); q=query(o<<1|1,mid+1,r,mid+1,q2,val); p.first+=q.first; p.second+=q.second; return p; }}tr;int sum[maxn];void solve1(){ for(int i=1;i<=C;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } int x,x1,y1,x2,y2; tot=0; tr.build(1,1,C); pair<int,int> tmp; while(M--) { scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&x); if(sum[y2]-sum[y1-1]<x) { printf("Poor QLW\n"); continue; } int l=0,r=1001; while(l<r) { int mid=l+(r-l+1)/2; tmp=tr.query(1,1,C,y1,y2,mid); if(tmp.second<x)r=mid-1; else l=mid; } tmp=tr.query(1,1,C,y1,y2,l+1); printf("%d\n",(x-tmp.second-1)/l+1+tmp.first); }}int getsum(int x1,int y1,int x2,int y2,int x){ return f[x2][y2][x]-f[x1-1][y2][x]-f[x2][y1-1][x]+f[x1-1][y1-1][x];}void solve2(){ int x,x1,y1,x2,y2,sum; for(int i=1;i<=R;i++) { for(int j=1;j<=C;j++) { scanf("%d",&x); for(int k=1;k<=1000;k++) f[i][j][k]+=f[i-1][j][k]+f[i][j-1][k]-f[i-1][j-1][k]; f[i][j][x]++; } } while(M--) { scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&sum); int cnt=0,ans=0,flag=0; for(int i=1000;i>0;i--) { int tmp=getsum(x1,y1,x2,y2,i); if(cnt+tmp*i<sum)cnt+=tmp*i,ans+=tmp; else { flag=1; ans+=(sum-cnt-1)/i+1; break; } } if(flag)printf("%d\n",ans); else printf("Poor QLW\n"); }}int main(){ scanf("%d%d%d",&R,&C,&M); if(R==1)solve1(); else solve2(); return 0;}
0 0
- 线段树套treap+dp(BZOJ1926)
- 线段树套Treap
- bzoj3196(线段树套treap)
- 线段树套treap(ZOJ2112)
- 线段树套treap三题
- Zoj 2112 线段树套Treap
- [ 线段树套treap ] [ TJOI2016&&HEOI2016 ] BZOJ4552
- bzoj3295(线段树套平衡树(treap))
- LA 3294 The Ultimate Bamboo Eater (线段树套Treap)
- BZOJ 4553 [Tjoi2016&Heoi2016]序列 线段树套treap
- BZOJ1901 ZOJ2112 线段树+treap (线段树套线段树)
- BZOJ 3196 二逼平衡树 树套树(线段树套Treap)
- BZOJ 3196 Tyvj 1730 二逼平衡树(线段树套treap)
- 【bzoj3196】【坑】Tyvj 1730 二逼平衡树 线段树套Treap/Splay
- BZOJ 3196(Tyvj 1730 二逼平衡树-线段树套Treap)
- bzoj3196 Tyvj 1730 二逼平衡树 线段树套treap
- 【ZOJ】2112 Dynamic Rankings 动态第K大【线段树套treap】
- BZOJ 3295 CQOI 2011 动态逆序对 线段树套Treap
- 【大型网站技术实践】初级篇:借助LVS+Keepalived实现负载均衡
- Java NIO系列教程(七) FileChannel
- 支付宝 IOS
- Unable to run app in Simulator报错
- Android xml资源文件中@、@android:type、@*、?、@+含义和区别
- 线段树套treap+dp(BZOJ1926)
- Java NIO系列教程(八) SocketChannel
- jquery插件的编写
- Java NIO系列教程(九) ServerSocketChannel
- Java NIO系列教程(十) Java NIO DatagramChannel
- Android中使用Handler造成内存泄露的分析和解决
- Xen事件通道详细介绍(四)
- EditText只显示光标不弹出软键盘的方法
- Java NIO系列教程(十一) Pipe