HDU 6107 Typesetting(倍增法 17多校第六场)
来源:互联网 发布:淘宝双十一红包口令 编辑:程序博客网 时间:2024/05/18 13:25
题目大意
在一个页面上有n个单词组成的一段话和一个图片,页面宽度、图片宽度、图片两边边距是确定的。告诉了你这段话中每个单词的长度,这些单词在页面中要满足:
- 图片上不能放单词
- 一行中的连续区间中的两个单词之间要有一个空格
现在给出Q组询问,每次询问给出一个x和h,x表示图片的起始行数,h表示图片长度
问这些单词加图片一共覆盖了多少行分析
采用倍增的做法
整个页面可以分为两个部分,有图片的行和没有图片的行
用f1[i][j] 表示不含图片的部分以第i个单词作为开头,行数为2j 的一段内单词的总数
用f2[i][j] 表示含图片的部分以第i个单词作为开头,行数为2j 的一段内单词的总数
然后就是通过倍增的思想对三段分别进行处理总结
这道题代码比较难写,边界条件处理起来比较复杂代码
#include<bits/stdc++.h>using namespace std;const int MAXN=200005;int T;int n,w,pw,lw;//单词数,页面宽度,图片宽度,页左边距int a[MAXN];int Q;//查询次数int xi,hi;int mx;int f1[MAXN][30];//f1[i][j]表示从第i个单词开头,占据2^j行能放置的最大单词数int f2[MAXN][30];//f1[i][j]表示有图片的情况下从第i个单词开头,占据2^j行能放置的最大单词数void Init_ST(){ memset(f1,0,sizeof(f1)); memset(f2,0,sizeof(f2)) a[n+1]=w+1;//在最后添加一个虚拟的单词长度超过页面宽度 for(int i=1;i<=n;i++)//求出f1[i][1] { int tw=a[i];//宽度 int j=i+1; while(tw+a[j]+1<=w){tw+=a[j]+1;j++;} f1[i][0]=j-i; } for(int k=1;(1<<k)<=mx;k++) { for(int i=1;i<=n;i++) { int t=f1[i][k-1]; f1[i][k]=t+f1[i+t][k-1]; } } for(int i=1;i<=n;i++) { int j=i; int tw=0; if(tw+a[j]<=lw){tw+=a[j];j++;} while(tw+a[j]+1<=lw) {tw+=a[j]+1;j++;} tw=0; int rw=w-pw-lw; if(tw+a[j]<=rw){tw+=a[j];j++;} while(tw+a[j]+1<=rw){ tw+=a[j]=1;j++;} f2[i][0]=j-i; } for(int k=1;(1<<k)<=mx;k++) { for(int i=1;i<=n;i++) { int t=f2[i][k-1]; f2[i][k]=t+f2[i+t][k-1]; } }}int RMQ1(int i,int x)//不含图片,以i开头长度为x的段落之后的单词标号{ if(x==0)return i; while(x!=0 && i<=n) { int j=0; while((1<<(j+1))<=x)j++; i+=f1[i][j]; x-=(1<<j); } return i;}int RMQ2(int i,int x)//含图片,以i开头长度为x的段落之后的单词标号{ if(x==0)return i; while(x!=0 && i<=n) { int j=0; while((1<<(j+1))<=x)j++; i+=f2[i][j]; x-=(1<<j); } return i;}int RMQ3(int i)//不含图片,以i开头到末尾的行数{ int ans=0; while(i<=n) { int j=0; while(i+f1[i][j+1]<=n)j++; i+=f1[i][j]; ans+=(1<<j); } return ans;}int Work(int x,int h){ int temp=RMQ3(1); if(temp<=x-1)return temp+h; int ans=x+h-1; int i=0; i=RMQ1(1,x-1); i=RMQ2(i,h); if(i<=n)ans+=RMQ3(i); return ans;}int main(){ scanf("%d",&T); while(T--) { mx=1000000;//设置一个最大的长度 scanf("%d%d%d%d",&n,&w,&pw,&lw); for(int i=1;i<=n;i++)scanf("%d",&a[i]); Init_ST(); scanf("%d",&Q); for(int i=1;i<=Q;i++) { scanf("%d%d",&xi,&hi); printf("%d\n",Work(xi,hi)); } }}/*22 7 4 31 331 22 25 23 8 2 31 1 311 1*/
阅读全文
1 0
- HDU 6107 Typesetting(倍增法 17多校第六场)
- HDU-6107 Typesetting(倍增法)
- HDU 6107 Typesetting(ST)
- HDU 6105 Gameia(树上博弈 17多校第六场)
- HDU 6098 Inversion (思维 17多校第六场)
- 多校第一场 1009 hdu 5296 Annoying problem(dfs序+在线倍增lca)
- hdu 4662 MU Puzzle 多校第六场
- 2013 多校第六场 hdu 4662 MU Puzzle
- hdu 4662 MU Puzzle 13多校第六场
- hdu 4658 整数划分+五边形定理 多校第六场
- 2013 多校第六场 hdu 4655 Cut Pieces
- 2013 多校第六场 hdu 4665 Unshuffle
- hdu 4925 Apple Tree 2014多校第六场 贪心
- 多校第六场 HDU 4927 JAVA大数类+模拟
- HDU 4930 Fighting the Landlords 多校第六场
- 多校第六场 Apple Tree hdu 4925
- 多校第六场 1003 hdu 5355 Cake(贪心)
- 多校第六场 1008 hdu 5360 Hiking(贪心+STL)
- Windows.url.createObjectURL()
- 笔面试
- MVVM + dataBinding
- hdu5924Mr. Frog’s Problem
- hdu6112-今夕何夕
- HDU 6107 Typesetting(倍增法 17多校第六场)
- jQuery获取两个元素之间的同胞元素(适用于无限分类的显示隐藏)
- spring-cloud-producter生产者(三)
- Java动态代理
- div垂直居中,图片垂直居中
- python可变参数
- 递归
- 系统管理员资源大全
- JZOJ 5275. 水管