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. GitHub 用户排行榜

    排行榜预览网址:Github | Githack | UNPKG | Gitee Github 中国用户排名,全球仓库 Star 最多排名,通过 Github API v3 来生成页面数据,排行榜预览 ...

  2. ElasticSearch6.x版本聚合分析整理

    ElasticSearch6.x版本聚合分析整理 ES将聚合分析主要分为如下4类 Bucket,分桶类型,类似SQL中的GROUP BY语法 Metric,指标分析类型,如计算最大值 , 最小值,平均 ...

  3. Android:JNI与NDK(三)NDK构建的脚本文件配置

    友情提示:欢迎关注本人公众号,那里有更好的阅读体验以及第一时间获取最新文章 本文目录 一.前言 本篇我们介绍Android.mk与CMakeLists.txt构建NDK的配置文件,我们知道目前NDK的 ...

  4. Redis进阶应用:Redis+Lua脚本实现复合操作

    一.引言 Redis是高性能的key-value数据库,在很大程度克服了memcached这类key/value存储的不足,在部分场景下,是对关系数据库的良好补充.得益于超高性能和丰富的数据结构,Re ...

  5. Linux部署项目遇到问题解决

    使用Linux部署web项目,可能会遇到各种各样问题导致服务启动失败,以下是我近期部署项目遇到的问题以及解决方案 一.场景:把war包放入tomcat的webapps文件夹下,然后启动tomcat服务 ...

  6. 佳木斯集训Day6

    T1还是个找规律啊,记下b的个数,然后直接*2%10000000009就好了 #include <bits/stdc++.h> #define mo 1000000007 using na ...

  7. Java泛型使用的简单介绍

    目录 一. 泛型是什么 二. 使用泛型有什么好处 三. 泛型类 四. 泛型接口 五. 泛型方法 六. 限定类型变量 七. 泛型通配符 7.1 上界通配符 7.2 下界通配符 7.3 无限定通配符 八. ...

  8. 送礼物「JSOI 2015」RMQ+01分数规划

    [题目描述] 礼品店一共有N件礼物排成一列,每件礼物都有它的美观度.排在第\(i(1\leq i\leq N)\)个位置的礼物美观度为正整数\(A_I\).JYY决定选出其中连续的一段,即编号为礼物\ ...

  9. OCP培训 Oracle 12c/18c/19c OCP认证实战培训【送OCP优惠名额】

    一.OCP培训 Oracle 12c/18c/19c OCP认证全套实战培训[送OCP优惠名额],本课程内容 课程目标: 为满足想参加Oracle OCP考证的学员,风哥设计的一套比较全面OCP实战培 ...

  10. ZooKeeper系列(三)—— Zookeeper 常用 Shell 命令

    一.节点增删改查 1.1 启动服务和连接服务 # 启动服务 bin/zkServer.sh start #连接服务 不指定服务地址则默认连接到localhost:2181 zkCli.sh -serv ...