[cf 1236 E] Alice and the Unfair Game
题意:
给定一个长度为m的序列$A$,你有一个长度为n的棋盘,可以任选一个位置x作为起点。
在时刻$[1,m+1]$你可以向左或向右移动一格。
设时刻i你移动后所在的位置为$B_i$,你需要满足对于任意$1\leq i\leq m$,$A_{i}\neq B_{i}$。
求有多少对有序数对$(x,y)$,使得以x为起点且以y为终点的合法移动路径存在。
$n,m\leq 10^{5},1\leq A_{i}\leq n$。
题解:
首先观察出一个性质:设x向左最远走到l,向右最远走到r,则$[l,r]$中的位置都可以走到。
为什么呢?我们总可以在不超过m步走到这些位置,然后通过“反复横跳”的操作来躲避$A_{i}$(第m+1步的移动保证了这一点)。
考虑如何求出右边界$r(x)$,首先我们可以按照题意直接走。复杂度为$O(n^2)$貌似自闭。
当什么时候我们这一步走不了呢?设当前时间为t,走到了xt。
那么如果$t$后面的一个$i$能挡住我当且仅当其满足$A_{i}-xt=i-t$。
移个项,$A_{i}-i=xt-t$,那么将这两项视为两个点$(i,A_{i})$和$(t,xt)$,限制条件就相当于他们在同一条斜率为1的直线上。
那么现在就有两种做法,一种是维护这些直线然后$O(n)$线性处理,另外一种是用线段树模拟每一步走的操作。
观察博客的题目可知,我写的是后一种。
考虑在线段树中维护每个点x的位置$pos_{x}$,问题需要我们每次将所有能走的点往右走一步,也就是pos整体+1。
运用lazy标记的思想,我们可以每次仅将不能走的点-1,最后把pos整体+m即可。
如果这样处理的话,那么对于每个限制,(由第一个公式)它影响的就是所有$(pos+lazy)-t=A_{i}-i$的点。
因为增量lazy和t恰好抵消,于是每个限制影响的就是$pos=A_{i}-i$的点。
那么我们直接二分找到这样的一段(注意是一段),然后将其整体-1即可。
最终x的右边界就是$r(x)=seg(x)+m+1$,左边界处理方法类似,但注意移项出来是$A_{i}+i$。
复杂度$O(nlogn)$。
代码:
#include<bits/stdc++.h>
#define maxn 100005
#define maxm 500005
#define inf 0x7fffffff
#define ll long long using namespace std;
ll N,M,A[maxn],B[maxn],tr[maxn<<];
ll R[maxn],L[maxn],lz[maxn<<]; inline ll read(){
ll x=,f=; char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-;
for(;isdigit(c);c=getchar()) x=x*+c-'';
return x*f;
} inline void build(ll l,ll r,ll k){
if(l==r){tr[k]=l;return;}
ll mid=l+r>>;
build(l,mid,k<<);
build(mid+,r,k<<|);
return;
}
inline void add(ll l,ll r,ll x,ll y,ll v,ll k){
if(x<=l && r<=y){lz[k]+=v;return;}
ll mid=l+r>>;
if(x<=mid) add(l,mid,x,y,v,k<<);
if(y>mid) add(mid+,r,x,y,v,k<<|);
return;
}
inline ll query(ll l,ll r,ll p,ll k){
if(l==r) return tr[k]+lz[k];
ll mid=l+r>>;
if(p<=mid) return query(l,mid,p,k<<)+lz[k];
else return query(mid+,r,p,k<<|)+lz[k];
} int main(){
N=read(),M=read();
for(ll i=;i<=M;i++) A[i]=read();
if(N==){cout<<""<<endl;return ;}
build(,N,);
for(ll i=;i<=M;i++){
ll l=,r=N,ansl=,ansr=;
while(l<=r){
ll mid=l+r>>;
if(query(,N,mid,)<A[i]-i) ansl=mid,l=mid+;
else r=mid-;
}
ansl++,l=,r=N;
while(l<=r){
ll mid=l+r>>;
if(query(,N,mid,)<=A[i]-i) ansr=mid,l=mid+;
else r=mid-;
}
if(ansl<=ansr) add(,N,ansl,ansr,-,);
}
for(ll i=;i<=N;i++) R[i]=min(query(,N,i,)+M+,N);
memset(tr,,sizeof(tr));
memset(lz,,sizeof(lz));
build(,N,);
for(ll i=;i<=M;i++){
ll l=,r=N,ansl=,ansr=;
while(l<=r){
ll mid=l+r>>;
if(query(,N,mid,)<A[i]+i) ansl=mid,l=mid+;
else r=mid-;
}
ansl++,l=,r=N;
while(l<=r){
ll mid=l+r>>;
if(query(,N,mid,)<=A[i]+i) ansr=mid,l=mid+;
else r=mid-;
}
if(ansl<=ansr) add(,N,ansl,ansr,,);
}
for(ll i=;i<=N;i++) L[i]=max(query(,N,i,)-M-,1ll*);
ll ans=;
for(ll i=;i<=N;i++) ans+=R[i]-L[i]+;
cout<<ans<<endl;
return ;
}
E
[cf 1236 E] Alice and the Unfair Game的更多相关文章
- E. Alice and the Unfair Game(推导线段树)
题:https://codeforces.com/contest/1236/problem/E 粗自:https://www.cnblogs.com/YSFAC/p/11715522.html #in ...
- Codeforces 1236E. Alice and the Unfair Game
传送门 首先可以注意到对于固定的起点 $S$ ,它最终能走到的终点一定是一段区间 这个用反证法容易证明,假设合法区间存在断点,这个点左右都可以作为终点 那么分成区间断点在起点左边和起点右边讨论一下即可 ...
- Codeforces Round #593 (Div. 2)
传送门 A. Stones 签到. B. Alice and the List of Presents 单独考虑每个数的贡献即可. 答案为\((2^{m}-1)^n\). C. Labs 构造就类似于 ...
- cf C. Alice and Bob
http://codeforces.com/contest/347/problem/C 这道题就是求出n个数的最大公约数,求出n个数的最大值,总共有max1/gcd-n个回合.然后判断如果回合数%2= ...
- (中等) CF 585C Alice, Bob, Oranges and Apples,矩阵+辗转相除。
Alice and Bob decided to eat some fruit. In the kitchen they found a large bag of oranges and apples ...
- CF6C Alice, Bob and Chocolate
CF6C Alice, Bob and Chocolate 题目链接 写了一天搜索写的有点累了,就顺手水了一道CF的模拟题 这道题就是简单的模拟整个题的过程,注意最后输出的形式就好了QWQ AC代码如 ...
- CF #575 Div3
// 比赛链接:https://codeforces.com/contest/1196 // CF 2019.7.24 // 本想Div3手速场上分,结果卡在C题,掉了不少分. // 自闭了这么久,今 ...
- A - Alice and the List of Presents (排列组合+快速幂取模)
https://codeforces.com/contest/1236/problem/B Alice got many presents these days. So she decided to ...
- [cf]Codeforces Round #784(Div 4)
由于一次比赛被虐得太惨,,生发开始写blog的想法,于是便有了这篇随笔(找了个近期的cf比赛练练手(bushi))第一次写blog,多多包涵. 第二场cf比赛,第一场打的Div2,被虐太惨,所以第二场 ...
随机推荐
- 实验1c语言开发环境使用和数据类型,运算符和表达式
/*this is first c program*/ # include<stdio.h> int main() { printf("Hello Mars!"); ; ...
- Reconstructing Cloud-Contaminated Multispectral Images With Contextualized Autoencoder Neural Networks(自编码机重建云污染区)
1.逐像元输入输出与邻域输入输出,邻域处理是先flatten,再unflatten 2.用MDL方法(最小描述长度)寻找自编码机最佳隐藏层数 3.多目标优化方法寻找MDL方法的超参数,平衡MDL方法两 ...
- SpringCloud:学习Gateway网关拦截器的ServerWebExchange
1.Gateway的拦截器 我们要在项目中实现一个拦截器,需要继承两个类:GlobalFilter, Ordered GlobalFilter:全局过滤拦截器,在gateway中已经有部分实现,具体参 ...
- OpenFOAM——设置非均匀边界方法总结
在使用OpenFOAM求解的时候我们经常需要设置非均匀的边界,比如我们在计算层流的时候,很多时候需要入口为充分发展的入口边界,下面我们就以入口处为充分发展的层流速度分布为总结OpenFOAM当中设定不 ...
- 数据接口-免费版(股票数据API)
获取股票数据的源头主要有:数据超市.雅虎.新浪.Google.和讯.搜狐.ChinaStockWebService.东方财富客户端.证券之星.网易财经. 数据超市 2016年5月6日更新.根据最近频繁 ...
- Excel填坑[0]
Excel填坑[0] 本着一天水一贴的原则(放p),我又来填坑了.今天做一个很简单的排队图,虽然不难,但因为手机显示问题折腾了半天.感觉做图做表格不仅仅是靠技术,更重要的是思维. 就是这张图,看起来平 ...
- pymysql装饰器封装
pymysql装饰器封装 def openClose(fun): def run(sql=None): coon =pymysql.connect(host='localhost' ,port=330 ...
- 使用ssh-keygen生成私钥和公钥
1.使用ssh-keygen生成私钥和公钥 命令如下: ssh-keygen -t rsassh-keygen -t rsa -C "用户名自取"可以是邮箱 例子: fdipzon ...
- MySQL函数find_in_set介绍
MySQL函数find_in_set介绍 数据库中的某个字段我十以字符存储的,同时又以","隔开的.如果想要查询这个字段中包含某个字符串该怎么查询?使用like?感觉不妥,如果使用 ...
- Feign进行文件上传+表单调用
Feigin默认是不支持文件上传和表单提交的,需要做一些配置才能支持. 1.feign依赖 图中红色为form支持必须的jar. 2.添加自定义Encoder类: import static java ...