Inna and Sequence

题意:先给你一个n,一个m, 然后接下来输入m个数,表示每次拳击会掉出数的位置,然后输入n个数,每次输入1或0在数列的末尾加上1或0,如果输入-1,相应m序列的数的位置就会掉出来并且后面的数会向前补位(每次删除操作可以看作是同时进行的,只有删除结束之后才会进行补位),最后输出这个数列的剩下结果,如果数列为空就输出“Poor stack!”。

题解:一开始想到的思路还是和上次CF889F想到的一样,在删除的位置标记一下,然后每次2分去查找在前面删除操作之后现在需要删除的位置对应哪里,然后再进行相应的位置,注意的就是,要么从后往前删除,且用二分去查找开始的第一个点,因为m序列如果太大的话,每次删除都会有很多时间浪费在不能删除的位置上; 要么就是先把每次对应的全部位置找出来,再进行删除,因为每次删除都会对后面的删除产生影响。

 #include<cstdio>
using namespace std;
const int N = 1e6+;
int n, m, R;
int tree[N], a[N];
int ans[N];
int lowbit(int x)
{
return x&(-x);
}
void Add(int x)
{
while(x <= n)
{
tree[x]++;
x += lowbit(x);
}
}
int Query(int x)
{
int ret = ;
while(x > )
{
ret += tree[x];
x -= lowbit(x);
}
return ret;
}
int Find_pos(int pos)//找到以前删除之后的补位之后的对应位置
{
int l = pos, r = R;
while(l <= r)
{
int mid = l+r >> ;
int num = Query(mid);
if(mid == num + pos && ans[mid] != -)
{
return mid;
}
else if(mid < num+ pos) l = mid+;
else r = mid - ;
}
}
void Delete()
{
int l = , r = m;
int len = R - Query(R);
while(l <= r)//2分寻找每次开始删除的位置,倒着删除
{
int mid = l + r >> ;
if(len >= a[mid]) l = mid+;
else r = mid-;
}
for(int i = l-; i > ; i--)
{
int pos = Find_pos(a[i]);
ans[pos] = -;
Add(pos);
}
}
int main()
{
scanf("%d%d",&n,&m);
for(int i = ; i <= m; i++)
scanf("%d",&a[i]);
R = ;
int t;
for(int i = ; i <= n; i++)
{
scanf("%d",&t);
if(t == -)
Delete();
else ans[++R] = t;
}
if(R - Query(R) == ) printf("Poor stack!\n");
else
{
for(int i = ; i <= R; i++)
{
if(ans[i] == -) continue;
printf("%d",ans[i]);
}
}
return ;
}

然后上面那个思路竟然被队长说TLE, 然后最后修改了n发,最终走到了和下面这个版本耗时差不多的慢几十ms的线段树版本操作。

开一棵线段树保存有效长度,然后每次通过有效长度去删除就好了。同时可以将m序列转化成有效长度,将删除数组的每一位减去前面的个数,就可以从头开始进行删除操作,

因为你每删除一次数据,有效长度就会减一,所以如果轮到第m个数,那么对于刚开始删除的序列的有效长度就已经减去m-1了。

 #include<cstdio>
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int N = 1e6+;
int n, m;
int tree[N<<], ans[N], Delt[N];
void Add(int L,int C,int l, int r, int rt)
{
tree[rt]++;
if(l == r)
{
ans[l] = C;
return ;
}
int m = l+r >> ;
if(L <= m) Add(L,C,lson);
else Add(L,C,rson);
}
void Delete(int Num, int l, int r, int rt)
{
tree[rt]--;
if(l == r)
{
ans[l] = -;
return ;
}
int m = l+r >> ;
if(tree[rt<<] >= Num) Delete(Num, lson);
else Delete(Num-tree[rt<<],rson);
}
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0);
//cout.tie(0);
scanf("%d%d",&n,&m);
for(int i = ; i < m; i++)
{
scanf("%d",&Delt[i]);
Delt[i] -= i;//将位置转化成长度
}
int tot = ;
int tmp;
for(int i = ; i <= n; i++)
{
scanf("%d",&tmp);
if(tmp != -)
Add(++tot,tmp,,n,);
else
{
for(int i = ; i < m; i++)
{
if(tree[] < Delt[i]) break;
else Delete(Delt[i],,n,);
}
}
}
if(tree[] == ) printf("Poor stack!\n");
else
{
for(int i = ; i <= tot; i++)
if(ans[i] != -)
printf("%d",ans[i]);
}
return ;
}

Codefroces 374 B Inna and Sequence (树状数组 || 线段树)的更多相关文章

  1. 洛谷P2414 阿狸的打字机 [NOI2011] AC自动机+树状数组/线段树

    正解:AC自动机+树状数组/线段树 解题报告: 传送门! 这道题,首先想到暴力思路还是不难的,首先看到y有那么多个,菜鸡如我还不怎么会可持久化之类的,那就直接排个序什么的然后按顺序做就好,这样听说有7 ...

  2. 树状数组 && 线段树应用 -- 求逆序数

    参考:算法学习(二)——树状数组求逆序数 .线段树或树状数组求逆序数(附例题) 应用树状数组 || 线段树求逆序数是一种很巧妙的技巧,这个技巧的关键在于如何把原来单纯的求区间和操作转换为 求小于等于a ...

  3. hdu1394(枚举/树状数组/线段树单点更新&区间求和)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1394 题意:给出一个循环数组,求其逆序对最少为多少: 思路:对于逆序对: 交换两个相邻数,逆序数 +1 ...

  4. hdu 5147 Sequence II【树状数组/线段树】

    Sequence IITime Limit: 5000/2500 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Problem ...

  5. hdu 1166:敌兵布阵(树状数组 / 线段树,入门练习题)

    敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submis ...

  6. CodeForces–830B--模拟,树状数组||线段树

    B. Cards Sorting time limit per test 1 second memory limit per test 256 megabytes input standard inp ...

  7. 数据结构--树状数组&&线段树--基本操作

    随笔目的:方便以后对树状数组(BIT)以及基本线段树的回顾 例题链接:http://acm.hdu.edu.cn/showproblem.php?pid=1166 例题:hdu 1166 敌兵布阵 T ...

  8. BZOJ_1901_&_ZJU_2112_Dynamic_Rankings_(主席树+树状数组/线段树+(Treap/Splay))

    描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1901 给出一个长度为n的数列A,有m次询问,询问分两种:1.修改某一位置的值;2.求区间[l, ...

  9. BZOJ 3333 排队计划 树状数组+线段树

    题目大意:给定一个序列.每次选择一个位置,把这个位置之后全部小于等于这个数的数抽出来,排序,再插回去,求每次操作后的逆序对数 首先我们每一次操作 对于这个位置前面的数 因为排序的数与前面的数位置关系不 ...

  10. 第十四个目标(dp + 树状数组 + 线段树)

    Problem 2236 第十四个目标 Accept: 17    Submit: 35 Time Limit: 1000 mSec    Memory Limit : 32768 KB  Probl ...

随机推荐

  1. python 感悟

    * 优美胜于丑陋.* 显式胜于隐式.* 简单胜于复杂.* 复杂胜于难懂.* 扁平胜于嵌套.* 稀疏胜于紧密.* 可读性应当被重视.* 尽管实用性会打败纯粹性,特例也不能凌驾于规则之上.* 不要忽略任何 ...

  2. 【iOS】NSString rangeOfString

    今天遇到了 NSString 的 rangeOfString 方法,刚遇到的时候不知道什么作用, 网上找到了一篇文章,介绍得挺简洁,代码如下: NSString *str1 = @"can ...

  3. 彻底理解kubernetes CNI

    kubernetes各版本离线安装包 CNI接口很简单,特别一些新手一定要克服恐惧心里,和我一探究竟,本文结合原理与实践,认真读下来一定会对原理理解非常透彻. 环境介绍 我们安装kubernetes时 ...

  4. bit、byte、kb、mb、g的区别

    1Byte=8bit1KB=1024Byte(字节)=8*1024bit1MB=1024KB1GB=1024MB1TB=1024GB bit是计算机数据的最小单元.要么是0,要么是1. byte 关键 ...

  5. RabbitMQ(四):使用Docker构建RabbitMQ高可用负载均衡集群

    本文使用Docker搭建RabbitMQ集群,然后使用HAProxy做负载均衡,最后使用KeepAlived实现集群高可用,从而搭建起来一个完成了RabbitMQ高可用负载均衡集群.受限于自身条件,本 ...

  6. python创建虚拟环境(Windows)

    >>>构建Python虚拟环境的目的是为了防止真实环境被破坏!!! >>>每一个项目建议用一个虚拟环境为了防止软件版本号冲突!!! 1.在终端切换到一个新的磁盘 如 ...

  7. 【故障公告】发布 .NET Core 版博客站点引起大量 500 错误

    非常抱歉,今天上午的博客站点故障给大家带来了很大的麻烦,请大家谅解.这次故障是我们发布 .NET Core 版博客站点引起的,虽然我们进行了充分的准备,但还是低估了高并发下的复杂问题. 以下是故障背景 ...

  8. Jquery 实现添加删除,checkbok 的全选,反全选,但是批量删除没有实现

    <!DOCTYPE html><html> <head>  <meta charset="utf-8" />  <title& ...

  9. ArrayList 的使用方法【摘要】

    ArrayList 的使用方法 1.什么是ArrayList ArrayList就是传说中的动态数组,用MSDN中的说法,就是Array的复杂版本,它提供了如下一些好处: (1)动态的增加和减少元素 ...

  10. java多线程中wait/notify/sleep/join/yield方法以及多线程的六种状态

    刚开始学线程的时候也是被这几个方法搞的云里雾里的,尤其是一开始看的毕老师的视频,老师一直在强调执行权和执行资格,看的有点懵逼,当然不是说毕老师讲的不好,就是自己有点没听明白,后来复习看了一些其他的博客 ...