题目描述

  有一个陶瓷瓶周围有\(n\)个可以印花的位置。第\(i\)个与第\(i+1\)个位置之间的距离为\(d_i\),在第\(i\)个位置印图案要\(t_i\)秒。

  机器刚开始在\(0\)号位置,可以以\(1\)单位长度每秒的速度移动。

  一个位置只能印一个图案。

  现在有\(m\)秒,问你最多能印几个图案。

  保证时间不足以绕陶瓷瓶一圈。

  \(n\leq 100000\)

题解

  肯定是先往一边移动在移动到另外一边。

  不妨设先往右边移动,那么右边的距离就要\(\times 2\)。

  求出每边印\(i\)个印花最少要多少秒。

  然后把两边合并即可。

  考虑怎么求。

  显然印\(i+1\)个印花的最优方案所需要移动的最右端点肯定在印\(i\)个印花的右边。

  证明:考虑反证法。

  设\(f(i,j)\)为印\(i\)个印花且最右端点为\(j\)的代价,\(a(i,j)\)为在前\(i\)个端点印印花所需要的第\(j\)短时间。

  设印\(i\)个印花的最优方案所需要移动的最右端点为\(j\),\(i+1\)个的右端点是\(k(k<j)\)

  那么有\(f(i,j)<f(i,k),a(j,i+1)<a(k,i+1),f(i+1,j)>f(i+1,k)\)

  但是前两项加起来是第三项,所以不合法。

  然后就可以分治了。

  设当前要求印\(l\)个到\(r\)个的答案,答案区间为\([sl,sr]\)。

  先求出印\(mid=\frac{l+r}{2}\)个的答案和右端点位置\(k\),可以通过枚举右端点得到。

  \([l,mid-1]\)的右端点位置在\([sl,k]\),\([mid+1,r]\)的右端点位置在\([k,sr]\)

  然后分治下去即可。

  求前面\(i\)个位置最小的\(j\)个印印花的时间可以通过可持久化线段树得到。

  时间复杂度:\(O(n\log^2n)\)

代码

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<utility>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
int q;
char cc[10000010];
int tt;
int h[100010];
ll rd()
{ll s=0;int c;while((c=cc[tt++])<'0'||c>'9');s=c-'0';while((c=cc[tt++])>='0'&&c<='9')s=s*10+c-'0';return s;
}
namespace seg
{int ls[4000010];int rs[4000010];ll s[4000010];int sz[4000010];int cnt;int insert(int p1,int &x,int l,int r){int p=++cnt;ls[p]=ls[p1];rs[p]=rs[p1];s[p]=s[p1]+h[x];sz[p]=sz[p1]+1;if(l==r)return p;int mid=(l+r)>>1;if(x<=mid)ls[p]=insert(ls[p],x,l,mid);elsers[p]=insert(rs[p],x,mid+1,r);return p;}ll query(int p,int x,int l,int r){if(l==r)return (ll)x*h[l];int mid=(l+r)>>1;int lsz=sz[ls[p]];if(x<=lsz)return query(ls[p],x,l,mid);return s[ls[p]]+query(rs[p],x-lsz,mid+1,r);}
}
int rt[100010];
int n;
ll m;
ll d[100010];
int t[100010];
ll a[100010];
ll f1[100010];
ll f2[100010];
ll g1[100010];
ll g2[100010];
int b[100010];
int c[100010];
int e[100010];
int f[100010];
ll &mm=m;
void gao(int l,int r,int sl,int sr,ll *s)
{if(l>r)return;int mid=(l+r)>>1;ll ans=0x3fffffffffffffffll;int i;int m=sr;for(i=sl;i<=sr;i++)if(i>=mid&&a[i-1]<=mm){ll v=a[i-1]+seg::query(rt[i],mid,0,q);if(v<ans){ans=v;m=i;}}s[mid]=ans;gao(l,mid-1,sl,m,s);gao(mid+1,r,m,sr,s);
}
void gao(ll *s)
{memset(rt,0,sizeof rt);seg::cnt=0;int i;for(i=1;i<=n;i++)rt[i]=seg::insert(rt[i-1],c[i],0,q);gao(1,n,1,n,s);
}
int main()
{
#ifndef ONLINE_JUDGEfreopen("a.in","r",stdin);freopen("a2.out","w",stdout);
#endiffread(cc+1,10000000,1,stdin);
//  scanf("%d%lld",&n,&m);n=rd();m=rd();int i;q=0;for(i=1;i<=n;i++)
//      scanf("%lld%lld",&d[i],&t[i]);{d[i]=rd();t[i]=rd();h[++q]=t[i];}sort(h+1,h+q+1);q=unique(h+1,h+q+1)-h-1;for(i=1;i<=n;i++)t[i]=lower_bound(h+1,h+q+1,t[i])-h;for(i=1;i<=n;i++){a[i]=d[i];c[i]=t[i];}for(i=1;i<=n;i++)a[i]+=a[i-1];gao(f1);for(i=1;i<=n;i++)a[i]*=2;c[1]=0;gao(g1);reverse(t+2,t+n+1);reverse(d+1,d+n+1);for(i=1;i<=n;i++){a[i]=d[i];c[i]=t[i];}for(i=1;i<=n;i++)a[i]+=a[i-1];gao(f2);for(i=1;i<=n;i++)a[i]*=2;c[1]=0;gao(g2);int ans=0;for(i=1;i<=n;i++)if(f1[i]<=m)ans=max(ans,i);for(i=1;i<=n;i++)if(f2[i]<=m)ans=max(ans,i);int j;j=n;for(i=1;i<=n;i++){while(j&&f1[i]+g2[j]>m)j--;if(!j)break;ans=max(ans,i+j-1);}j=n;for(i=1;i<=n;i++){while(j&&f2[i]+g1[j]>m)j--;if(!j)break;ans=max(ans,i+j-1);}printf("%d\n",ans);return 0;
}

转载于:https://www.cnblogs.com/ywwyww/p/8514572.html

【XSY2732】Decalcomania 可持久化线段树 分治相关推荐

  1. BZOJ4012[HNOI2015]开店——树链剖分+可持久化线段树/动态点分治+vector

    题目描述 风见幽香有一个好朋友叫八云紫,她们经常一起看星星看月亮从诗词歌赋谈到 人生哲学.最近她们灵机一动,打算在幻想乡开一家小店来做生意赚点钱.这样的 想法当然非常好啦,但是她们也发现她们面临着一个 ...

  2. 2019.01.13 bzoj4137: [FJOI2015]火星商店问题(线段树分治+可持久化01trie)

    传送门 题意:序列上有nnn个商店,有两种事件会发生: sss商店上进购标价为vvv的一个物品 求编号为[l,r][l,r][l,r]之间的位置买ddd天内新进购的所有物品与一个数xxx异或值的最大值 ...

  3. Codeforces1422 F.Boring Queries(根号分治+线段树+可持久化线段树)

    题意: 解法: 如果问题可以离线,那么莫队可以直接冲过去,可惜离不得. 每个数最多只有一个>sqrt的质因子,sqrt(2e5)<90, 开90棵线段树分别维护前90个质因子的区间最大指数 ...

  4. 3237: [Ahoi2013]连通图 线段树分治

    题解: cf765f cf671e bzoj4184 bzoj4552 线段树分治裸题 还是介绍一下线段树分治 这个东西其实挺简单但也挺有用的 可以把删除+插入操作变成只有插入(倒着就是删除) 像这一 ...

  5. P5787 二分图 /【模板】线段树分治(线段树分治、并查集)

    关于什么是合理的实现 解析 本题把并查集写在了题面上 然而,我却一直沉浸在一个及其通用的判断二分图的方法中: 一个图是二分图的充要条件是它没有奇环 怎么维护这个玩意?带权并查集! 怎么套线段树分治?可 ...

  6. [CTSC2016]时空旅行 (线段树分治)

    前言 昨天学习了线段树分治,算法比较抽象,没有学得太具体,今天做一道例题练练手 --自闭前 题面上洛谷 题意 维护若干个集合,每个集合都是由一个编号比它小的集合加入一个二元组(x,c)(x,c)(x, ...

  7. 越野赛车问题——线段树分治+并查集

    题目 [题目描述] 小 $H$ 是一位优秀的越野赛车女选手.现在她准备在 $A$ 山上进行赛车训练. $A$ 山上一共有 $n$ 个广场,编号依次为 $1$ 到 $n$ ,这些广场之间通过 $n-1$ ...

  8. 【线段树分治 线性基】luoguP3733 [HAOI2017]八纵八横

    不知道为什么bzoj没有HAOI2017 题目描述 Anihc国有n个城市,这n个城市从1~n编号,1号城市为首都.城市间初始时有m条高速公路,每条高速公路都有一个非负整数的经济影响因子,每条高速公路 ...

  9. bzoj 4025 二分图——线段树分治+LCT

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4025 线段树分治,用 LCT 维护链的长度即可.不过很慢. 正常(更快)的方法应该是线段树分 ...

  10. BZOJ 3483 SGU505 Prefixes and suffixes(字典树+可持久化线段树)

    [题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=3483 [题目大意] 给出一些串,同时给出m对前缀后缀,询问有多少串满足给出的前缀后缀模 ...

最新文章

  1. python 网页cookie的使用
  2. webpack+vue搭建基础
  3. pytorch比较Tensor
  4. 【干货分享】推荐5个可以让你事半功倍的Python自动化脚本
  5. 卷积神经网络-目标探测
  6. JAVA进阶教学之(Enum枚举类)
  7. C语言各种类型数据的输出显示
  8. java解析csv文件工具类,java操作CSV文件工具类
  9. 数据仓库模型(星型模型和雪花模型 )
  10. win10安装iNode客户端软件就不能连接无线网络的问题解决
  11. Nmap小技巧——探测大网络空间、局域网中的存活主机
  12. photoshopCS6软件的安装和破解方法
  13. 微信渐变国旗头像来了!一键生成
  14. 汽车控制器CAN通信DBC文件工具:EXCEL生成DBC和生成代码
  15. 押对春节档《流浪地球》 阿里影业的专业进击之路
  16. 人生苦短_人生苦短的说说、句子及图片
  17. Artiely Vue Admin - 基于蚂蚁金服Ant Design构建的高颜值开源管理后台UI框架
  18. Mysql对应的dul_DUL 恢复简单表测试
  19. 【5GNR物理层】-NR物理层概述
  20. java虚拟机笔记—运行时数据区域

热门文章

  1. python插排_PythonTkinter接收插座不接收
  2. 局部内部类使用局部变量应注意什么?
  3. python k线合成_在VNPY中策略中,使用分钟线合成日K线
  4. prometheus 筛选不同的cpu核心
  5. 基于Java的图书管理系统
  6. lol游戏挂机软件_“本不想挂机,但系统不让重连!”LOL成“挂机联盟”,5局3挂机...
  7. java多线程-线程安全
  8. L3-014 周游世界 (30分)
  9. podman 在 windows 安装
  10. 阶段1 语言基础+高级_1-3-Java语言高级_08-JDK8新特性_第1节 常用函数接口_2_函数式接口的使用...