博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
[HNOI/AHOI2018]转盘
阅读量:5129 次
发布时间:2019-06-13

本文共 2511 字,大约阅读时间需要 8 分钟。

, ,

,以及

相关题目:

可以发现转化之后你留在原地一定是不优的 , 也就是说你会一直往前走 , 其实区别在于开始的时间

比如原来的最优解为\(a=\{ 1,2,3,6,7 \}\) 可以转化为 \(a=\{3,4,5,6,7\}\)

枚举出发时间\(t\)出发点\(i\) , 枚举等待时间最长的点\(j\) , 则有\[ans=min_i\{max\{T_j-(j-i)\}+n-1\}\]

\(x_i=T_i-i\) , 即\[ans=min_i\{max\{x_j\}+i\}+n-1\]

又有\(x_j>x_{j+n}\) , 所以\(x_{j+n}\)对枚举最大值不会有影响 , 线段树上询问的范围也就可以从\([i,i+n-1]\)换为\([i,2n]\)

线段树维护单调栈结构 , 记\(mx[i] = max\{T_j-j \} , ans[i] = min\{max\{T_j-j\}+i\}\)

非常好的题 , 代码也很值得推敲 , 非常值得借鉴

具体细节见代码
维护单调栈的信息时维护整个区间非常不好搞 , 可以只维护一半的信息 , 另一半通过动态的比较得出
往左边继续找的时候 , 要记得比一下右边的答案 ; 往右边继续找的时候 , 要记得比一下左边的答案 ;
注释更新于\(19.3.31\)

#include
#include
#include
#include
#define debug(...) fprintf(stderr,__VA_ARGS__)#define Debug(x) cout<<#x<<"="<
<
57){if(c=='-')f=-1;c=getchar();} while(c>=48&&c<=57)x=(x<<3)+(x<<1)+(c&15),c=getchar(); return f*x;}const int MAXN=2e5+5;int a[MAXN];int n,m,type,lastans;struct SGT{// ans[i] = min{ max{ Tj-j } + i } 定义为在左儿子中的答案// mx[i] = max{ Tj-j }//这里懒得卡什么空间之类的,枚举范围直接到2n,方便想,反正也不会错 int ans[MAXN<<2],mx[MAXN<<2];#define ls (rt<<1)#define rs (rt<<1|1) //要求min{max{Xj}+i},所以i要尽可能小,所以维护一半信息的话就应该是把右边的参数传到左边 //还是当做模板记下来吧... inline int query(int rt,int l,int r,int tmp){//得到上一层区间左半边的答案 //核心:用到tmp或者把tmp继续往下传 if(l==r) return l+max(mx[rt],tmp);//特判长度为1:必须根据定义 int mid=(l+r)>>1; //直接返回答案也变成了直接传一半的参到另一半 if(mx[rs]>=tmp) return min(ans[rt],query(rs,mid+1,r,tmp));//右边的mx更大,可能答案在右边,但也要记得比较左边的答案ans[rt] else return min(query(ls,l,mid,tmp),tmp+mid+1);//应该往左边找,而右边的答案是tmp+mid+1(已经判过tmp>mx[rs]) } inline void pushup(int rt,int l,int r,int mid){ //维护最值的写法:直接把一半的参传到另一半去比较,维护某个半边的答案,这样才能做到另半边能够动态的比较得出 ans[rt]=query(ls,l,mid,mx[rs]); mx[rt]=max(mx[ls],mx[rs]);//mx[]很好更新 } inline void build(int rt,int l,int r){ if(l==r){ ans[rt]=a[l]; mx[rt]=a[l]-l; return; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); pushup(rt,l,r,mid);//非常骚的线段树维护单调栈结构的pushup() } inline void modify(int rt,int l,int r,int x){ if(l==r){ ans[rt]=a[l]; mx[rt]=a[l]-l; return; } int mid=(l+r)>>1; if(x<=mid) modify(ls,l,mid,x); else modify(rs,mid+1,r,x); pushup(rt,l,r,mid); }#undef ls#undef rs}T;int main(){ n=read(),m=read(),type=read(); for(int i=1;i<=n;i++) a[i]=a[i+n]=read(); T.build(1,1,n<<1); printf("%d\n",lastans=T.ans[1]+n-1); for(int i=1;i<=m;i++){ int x=read(),y=read(); if(type) x^=lastans,y^=lastans; a[x]=a[x+n]=y; T.modify(1,1,n<<1,x); T.modify(1,1,n<<1,x+n); printf("%d\n",lastans=T.ans[1]+n-1); }}

\(19.3.21\)

转载于:https://www.cnblogs.com/lizehon/p/10574757.html

你可能感兴趣的文章
GoLang安装
查看>>
Spring 4 官方文档学习(十一)Web MVC 框架之HTTP caching support
查看>>
蓝桥杯历届试题 错误票据
查看>>
Objective-C 继承与多态
查看>>
图像预处理第6步:分割,并在分割出来的字符外面画框以标识
查看>>
NTP时间服务
查看>>
2016.04.11,英语,《Vocabulary Builder》Unit 12
查看>>
CoreData教学完整版(封装我们自己的CoreData工具)_Dylan
查看>>
数据库锁
查看>>
Web项目去掉Js文件红叉
查看>>
Linux 学习路径图
查看>>
[LeetCode] 1. Two Sum 两数之和
查看>>
Linux系统shell脚本对字符串、数字、文件的判断
查看>>
Vue生命周期
查看>>
【WebStorm】前端工具开发利器webstrom专篇
查看>>
利用MySQL统计一列中不同值的数量方法示例
查看>>
微服务设计方法
查看>>
大项目之网上书城(九)——订单Demo
查看>>
Hexo主题实现多级分类显示
查看>>
UITableView-数据刷新
查看>>