真的是下定了巨大的决心来搞这一讲,果不其然耗了一晚上

开车旅行(真的是NOIP的题吗怎么这么恐怖)

首先,先用set把小A和小B从城市i出发,到达的下一个城市预处理出来。

f[i][j][k]表示走了2^i天,j城市出发,k表示谁开车,到达那个城市。

转移就是f[i][j][k]=f[i-1][f[i-1][j][k]][k] 相信很好理解

特别的i-1==0时,因为k是奇数,开车的人是变化的,所以f[i][j][k]=f[i-1][f[i-1][j][k]][k^1]

令da[i][j][k],db[i][j][k],分别表示小A和小B这个状态下走的路程

对于询问1,枚举所有的城市作为起点,然后基于二进制划分的思想,倒着for一步步在满足走的总路程<=x0的情况下前进,这样可以计算出小A走的路程和小B走的路程。找最大比值即可。

询问二就直接询问小A走的路程和小B走的路程了。同理可求。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
#include<set>
using namespace std;
typedef long long LL; int h[];
struct snode
{
int id,h;
snode(){}
snode(int ID,int H){id=ID;h=H;}
friend bool operator <(snode s1,snode s2){return s1.h<s2.h;}
};
set<snode>S;
set<snode>::iterator it,lt,rt;
int g[],I;
bool cmp(int g1,int g2){return (abs(h[g1]-h[I])<abs(h[g2]-h[I]))||(abs(h[g1]-h[I])==abs(h[g2]-h[I])&&h[g1]<h[g2]);} int Ago[],Bgo[];
int f[][][]; LL da[][][],db[][][]; LL A,B;
void solve(int now,int x0)
{
A=B=; int k=;
for(int i=;i>=;i--)
if(f[i][now][k]!=&&da[i][now][k]+db[i][now][k]<=x0)
{
x0-=da[i][now][k]+db[i][now][k];
A+=da[i][now][k],B+=db[i][now][k];
if(i==)k^=;
now=f[i][now][k];
}
} int main()
{
int n;
scanf("%d",&n);
for(int i=;i<=n;i++)scanf("%d",&h[i]);
memset(Ago,,sizeof(Ago));
memset(Bgo,,sizeof(Bgo));
for(int i=n;i>=;i--)
{
S.insert(snode(i,h[i]));
it=lt=rt=S.find(snode(i,h[i]));
int m=;
if(lt!=S.begin())
{
lt--,g[++m]=(*lt).id;
if(lt!=S.begin())lt--,g[++m]=(*lt).id;
}
rt++;
if(rt!=S.end())
{
g[++m]=(*rt).id;
rt++;if(rt!=S.end())g[++m]=(*rt).id;
}
I=i;sort(g+,g+m+,cmp);
if(m>)Ago[i]=g[];
if(m>)Bgo[i]=g[];
} memset(f,,sizeof(f));
for(int i=;i<=n;i++)
{
if(Ago[i]!=) f[][i][]=Ago[i], da[][i][]=abs(h[Ago[i]]-h[i]), db[][i][]=;
if(Bgo[i]!=) f[][i][]=Bgo[i], da[][i][]=, db[][i][]=abs(h[Bgo[i]]-h[i]);
}
for(int i=;i<=;i++)
for(int j=;j<=n;j++)
for(int k=;k<=;k++)
{
int l=k;if(i==)l=k^; if(f[i-][j][k]>)f[i][j][k]=f[i-][f[i-][j][k]][l];
if(f[i][j][k]>)
{
da[i][j][k]=da[i-][j][k]+da[i-][f[i-][j][k]][l];
db[i][j][k]=db[i-][j][k]+db[i-][f[i-][j][k]][l];
}
} int x0,ans;LL ansA=,ansB=;
scanf("%d",&x0);
for(int i=;i<=n;i++)
{
solve(i,x0); if(B==)A=;
if(A*ansB<ansA*B||(A*ansB==ansA*B&&h[i]>h[ans]))ansA=A,ansB=B,ans=i;
}
printf("%d\n",ans); int Q,x,y;
scanf("%d",&Q);
while(Q--)
{
scanf("%d%d",&x,&y);
solve(x,y);
printf("%lld %lld\n",A,B);
} return ;
}

开车旅行

Count The Repetitions

f[j][i]表示从s1第i个字符开始,能够表示出s2 2^j最少需要多少字符。

就有f[j][i]=f[j-1][i]+f[j-1][((i+f[j-1][i])-1)%s1len+1]

最后就枚举匹配的起始点,同样在不超过s1len*n1的情况下用二进制一步步跳,记录当前起始点的最优解更新答案就好了。

#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long LL; char s1[],s2[];
LL f[][];
int main()
{
freopen("2.in","r",stdin);
freopen("2.out","w",stdout);
while()
{
int n2,n1;
scanf("%s",s2+);if(s2[]=='}')break;
scanf("%d%s%d",&n2,s1+,&n1);
int s2len=strlen(s2+),s1len=strlen(s1+); bool bk=false;
for(int i=;i<=s1len;i++)
{
int p=i;f[][i]=;
for(int j=;j<=s2len;j++)
{
int cc=;
while(s1[p]!=s2[j])
{
p=p%s1len+;
cc++;if(cc>=s1len){printf("0\n");bk=true;break;}
}
p=p%s1len+;
f[][i]+=cc+;
if(bk==true)break;
}
if(bk==true)break;
}
if(bk==true)continue; for(int j=;j<=;j++)
for(int i=;i<=s1len;i++)
f[j][i]=f[j-][i]+f[j-][((i+f[j-][i])-)%s1len+]; LL m=;
for(int i=;i<=s1len;i++)
{
int x=i;LL ans=;
for(int j=;j>=;j--)
if(x+f[j][(x-)%s1len+]-<=s1len*n1)
x+=f[j][(x-)%s1len+], ans+=(<<j);
m=max(m,ans);
}
printf("%lld\n",m/n2);
}
return ;
}

Count The Repetitions

好像都是先预处理出下一步的状态,然后二进制划分啊

0x57 倍增优化DP的更多相关文章

  1. HZOJ 20190727 随(倍增优化dp)

    达哥T1 实际上还是挺难的,考试时只qj20pts,还qj失败 因为他专门给出了mod的范围,所以我们考虑把mod加入时间复杂度. $50\%$算法: 考虑最暴力的dp,设$f[i][j]$表示进行$ ...

  2. $Noip2012\ Luogu1081$ 开车旅行 倍增优化$ DP$

    Luogu Description Sol 1.发现对于每个城市,小A和小B的选择是固定的,可以预处理出来,分别记为ga[],gb[] 2.并且,只要知道了出发城市和出发天数,那么当前城市和小A,小B ...

  3. CodeForces - 1175E Minimal Segment Cover (倍增优化dp)

    题意:给你n条线段[l,r]以及m组询问,每组询问给出一组[l,r],问至少需要取多少个线段可以覆盖[l,r]区间中所有的点. 如果贪心地做的话,可以求出“从每个左端点l出发选一条线段可以到达的最右端 ...

  4. $CH0601\ Genius\ ACM$ 倍增优化DP

    ACWing Description 给定一个长度为N的数列A以及一个整数T.我们要把A分成若干段,使得每一段的'校验值'都不超过N.求最少需要分成几段. Sol 首先是校验值的求法: 要使得'每对数 ...

  5. POJ 1014 Dividing(多重背包, 倍增优化)

    Q: 倍增优化后, 还是有重复的元素, 怎么办 A: 假定重复的元素比较少, 不用考虑 Description Marsha and Bill own a collection of marbles. ...

  6. Codeforces 356D 倍增优化背包

    题目链接:http://codeforces.com/contest/356/problem/D 思路(官方题解):http://codeforces.com/blog/entry/9210 此题需要 ...

  7. 矩阵乘法优化DP复习

    前言 最近做毒瘤做多了--联赛难度的东西也该复习复习了. Warning:本文较长,难度分界线在"中场休息"部分,如果只想看普及难度的可以从第五部分直接到注意事项qwq 文中用(比 ...

  8. bzoj-4518 4518: [Sdoi2016]征途(斜率优化dp)

    题目链接: 4518: [Sdoi2016]征途 Description Pine开始了从S地到T地的征途. 从S地到T地的路可以划分成n段,相邻两段路的分界点设有休息站. Pine计划用m天到达T地 ...

  9. bzoj-1096 1096: [ZJOI2007]仓库建设(斜率优化dp)

    题目链接: 1096: [ZJOI2007]仓库建设 Description L公司有N个工厂,由高到底分布在一座山上.如图所示,工厂1在山顶,工厂N在山脚.由于这座山处于高原内陆地区(干燥少雨),L ...

随机推荐

  1. PHP中的魔术方法和魔术常量

    看上去好像挺烦人,但只要通过例子测试一下,就明白了.不做测试,只是看,第二天还是不明白.当然我在抄其他人的日志,然后希望能是自己的理解就好,原文地址PHP的魔术方法和魔术敞亮简介和使用--LaraBo ...

  2. Gradle sync failed: Could not find method android() for arguments 错误的解决办法

    这个问题本质上是Android-gradle的一个使用限制. 对应的英文文档android_tool文档 如果你的App包含了多个Android模块, 应该尽量避免给每个模块手动指定编译SDK版本. ...

  3. C#自动缩进排列代码的快捷键 c# 代码重新排版 变整齐

    C#自动缩进排列代码的快捷键:  ctrl + k + d 1.小技巧, 可以把最后一个}去掉, 重新写下,就可以达到排版的效果. 2.快捷键:编辑-高级-设置文档的格式 快捷键Ctrl+E,D,设置 ...

  4. logger日志

    Level 描述 ALL 各级包括自定义级别 DEBUG 指定细粒度信息事件是最有用的应用程序调试 ERROR 错误事件可能仍然允许应用程序继续运行 FATAL 指定非常严重的错误事件,这可能导致应用 ...

  5. Uoj #218. 【UNR #1】火车管理 可持久化线段树+思维

    Code: #include<bits/stdc++.h> #define maxn 500005 using namespace std; int n,Q,ty,lastans=0; i ...

  6. xpath 获取深圳房源信息并导出csv

    # -*- coding: utf-8 -*- # @Time : 2019/4/28 10:44 # @Author : wujf # @Email : 1028540310@qq.com # @F ...

  7. eas之kdtable格式化

    设置表.列.行或单元的格式化字符串 // 设置表table.getStyleAttributes().setNumberFormat(formatString); // 设置列column.getSt ...

  8. [luogu2054 AHOI2005] 洗牌 (数论)

    传送门 Solution 我们考虑每一步牌的变化: 前半部分的牌位置*2 后半部分的牌位置*2-n-1 那么我们可以看做是\(x\times 2^m\equiv l \pmod n\) 于是求个逆元就 ...

  9. Centos7.5虚拟机无法ping通网关、外网IP地址

    问题:前两天Centos7.5虚拟机关机,第二天重启后使用Xshell发现无法连接虚拟机,经检测发现虚拟机无法ping通192.168.1.1.无法ping通192.168.1.118(客户机)和ww ...

  10. js中window.location的用法

    用window.location处理解析当前页面URL window.location 对象所包含的属性 属性 描述 hash 从井号(#)开始的URL(锚点) host 主机名和当前URL的端口号 ...