题目描述

在如今的网络中,TCP 是一种被广泛使用的网络协议,它在传输层提供了可靠的通信服务。众所周知,网络是存在时延的,例如用户先后向服务器发送了两个指令 op1 和 op2,并且希望服务器先处理指令 op1,再处理指令 op2;但由于网络时延,这两个指令可能会失序到达,而导致服务器先执行了指令 op2,这是我们不希望看到的。TCP 协议拥有将失序到达的报文按顺序重组的功能,一种方法是给每一个报文打上一个时间戳。而你今天要实现的功能比这个要简单很多。我们需要你维护一个服务器,这个服务器的功能是一个简单的栈,你会接收三种用户的指令:
push x t — 表示将 x元素入栈,这条指令的时间戳为 t
pop t — 表示将栈顶元素弹出,这条指令的时间戳为 t
peak t — 用户询问现在栈顶元素的值,这条指令的时间戳为 t
当一条时间戳为 t 的指令到达时,你需要进行如下处理:
1.将所有之前执行的时间戳大于 t 的 push和 pop指令全部撤销
2.执行当前这条指令
3.按时间戳顺序重新执行在第 1 步被撤销的指令
注意你不需要撤销以及重新执行之前已经执行过的 peak 指令,也就是说每一条 peak指令只有在它到达的时候会被执行一次。
我们保证每一条指令的时间戳都是唯一的;若你在需要执行一条 pop 指令时发现当前栈为空,则当前你可以忽略这条指令。

输入

第一行包含一个整数 n,表示指令总数。接下来 n 行按指令到达服务器的顺序给出每一条指令,有三种类型
push x t
pop t
peak t

输出

对于每一条 peak指令,输出对应的答案占一行;若栈为空,输出−1。样例输入:
7
push 100 3
push 200 7
peak 4
push 50 2
pop 5
peak 6
peak 8

样例输出

100                                                             
50                                          

200                     

对于 100%的数据,1 <= n <= 300000,0 <= x,t <= 1000000000。

·突出题目重点难点:

①任务按照时间顺序执行,且输入的顺序不等于时间顺序

②上面条件的基础上,当前的PEAK命令只对在这之前的命令生效(不论时间先后,意思是后面输入的任务不会产生或被造成影响)

③必须模拟每一个出栈入栈的操作,否则无法得到每一时间点的栈顶状态

④n<=300000(logn<=18.2),猜测算法时间复杂度T的范围:

(O(n)的算法不太可能)     n*logn<=T<n*logn*logn

·解决方案:

基本思路可以想到是线段树,构造线段树的目的是维护每一个时刻栈的出栈进栈情况:如果线段树的各节点表示离散化后的时间点的化,那么里面的值就只有三种:1,0,-1。1表示进栈一个元素(不管这个元素具体是多少,这不是线段树要表示的),-1表示出栈一个元素,0表示这时刻是一个询问。那么维护线段树的区间和就可以用正负表示当前栈里有没有元素:

根据栈的性质,上面这幅图还有妙用:

栈是先进后出的:如果我们从x点开始,用一个指针i向右移动,就有如下结论:【区间和sun[i,x]第一次大于0时,PEAK要找的元素必定在这个区间之中】(假设这是读入的是PEAK x)

·在上图中可以看出,其实一旦sum[i,x]大于0,那么要找的数就是i这个位置push进去的数。但有一问题:线段树是无法将叶子节点一个个遍历的(而且这样做明显时间无法承受),所以我们只能用线段树区间拆分的思想进行类似的从后向前的遍历:

设我们的PEAK的时间是x,那么需要在1~x时间中寻找那个当前栈顶元素究竟是谁。设[1,x]为区间P,那么在线段树上拆分为a,b,c三段区间,然后从左至右遍历c,b,a当发现当前累加的区间和大于零时,则答案必在当前循环到的区间里(比如:sum(c)<0,sum(b+c)>0那么答案就在b区间中)。至于开头说的具体数值不用管,因为在b区间里你还要进行二分查找,那么最后找到的那个点(即答案),l==r那么只需要在读入的时候记录num[]就可以直接输出num[l]或者num[r]了。

·最后一个问题:a,b,c区间可能答案就在里面,但是包含了一些-1(比如说c区间长这样:{-1,-1,-1,-1,-1,-1,-1,-1,1}很明显,答案就是最后一个1,因为前面的pop即-1都无法影响它)。这些-1会让这个区间的sum变小从而导致错误。所以我们作为判断和大于零的依据不是区间和而是最大后缀和。

(注:其实后缀和做是一种改进方法,它的原版是直接在所有区间内二分找到最靠右边的sum大于0的时间点,但这样时间会爆炸)

  1. #include<stdio.h>
  2. #include<algorithm>
  3. #define go(i,a,b) for(int i=a;i<=b;i++)
  4. using namespace std;const int N=300004;
  5. struct TCP{char act;int Num,tim;}g[N];
  6. int n,Table[N],t,root,sz,list[N],k,Ll[N],Rr[N],ans;
  7. int lch[N*4],rch[N*4],sum[N*4],suffix[N*4],num[N];
  8. void build(int& u,int l,int r){u=++sz;if(l==r)return;int mid=l+r>>1;
  9. build(lch[u],l,mid);build(rch[u],mid+1,r);}
  10. void update(int u,int l,int r,int P,int val)
  11. {
  12. if(l==r){suffix[u]=sum[u]=val;return;}int mid=l+r>>1;
  13. P<=mid?update(lch[u],l,mid,P,val):update(rch[u],mid+1,r,P,val);
  14. sum[u]=sum[lch[u]]+sum[rch[u]];
  15. suffix[u]=max(suffix[lch[u]]+sum[rch[u]],suffix[rch[u]]);
  16. }
  17. void divide(int u,int l,int r,int L,int R)
  18. {
  19. if(l==L&&r==R){list[++k]=u;Ll[k]=l;Rr[k]=r;return;}
  20. int mid=l+r>>1;if(R<=mid)divide(lch[u],l,mid,L,R);
  21. else if(mid<L)divide(rch[u],mid+1,r,L,R);
  22. else divide(rch[u],mid+1,r,mid+1,R),
  23. divide(lch[u],l,mid,L,mid);
  24. }
  25. void dichotomy(int u,int l,int r,int tmp)
  26. {
  27. while(l<r){int mid=l+r>>1;
  28. if(tmp+suffix[rch[u]]>0)u=rch[u],l=mid+1;
  29. else tmp+=sum[rch[u]],u=lch[u],r=mid;}ans=num[l];
  30. }
  31. int main()
  32. {
  33. scanf("%d",&n);char s[5];int x,y;
  34. go(i,1,n)x=0,scanf("%s",s+1),s[2]=='u'?scanf("%d%d",&x,&y):scanf("%d",&y),
  35. g[i]=(TCP){s[2],x,y},Table[++t]=y;sort(Table+1,Table+t+1);
  36. go(i,1,n)g[i].tim=lower_bound(Table+1,Table+t+1,g[i].tim)-Table;
  37.  
  38. build(root,1,t);
  39. go(i,1,n)
  40. {
  41. if(g[i].act=='u')update(1,1,t,g[i].tim, 1),num[g[i].tim]=g[i].Num;
  42. if(g[i].act=='o')update(1,1,t,g[i].tim,-1);
  43. if(g[i].act=='e')
  44. {
  45. k=0;bool get_ans=0;int suffix_tot=0;
  46. divide(1,1,t,1,g[i].tim);
  47. go(j,1,k)if(suffix_tot+suffix[list[j]]>0)
  48. {
  49. dichotomy(list[j],Ll[j],Rr[j],suffix_tot);
  50. get_ans=1;printf("%d\n",ans);break;
  51. }
  52. else suffix_tot+=sum[list[j]];
  53. if(!get_ans)printf("-1\n");
  54. }
  55. }
  56. return 0;
  57. }//Paul_Guderian

狂欢的队伍已经远去,我只能看到自己的影子……————汪峰《尘土》

【TCP网络协议问题】的更多相关文章

  1. Ubuntu 18.04开启TCP网络协议BBR加速的方法(Google BBR 拥塞控制算法)

    TCP BBR 是Google给出的一个改良版的tcp网络协议,相当于在已有TCP协议的基础上打了个补丁的意思,这个改良版TCP协议对拥塞控制有很好的支持,对于网络较差的环境有不错的应用场景,当然这里 ...

  2. [TCP] 网络协议流程图

    之前在跟别人讲协议的时候总是找不到类似的图,这次再看python网络编程书籍的时候找到了一个,留存一份. 清晰的看到不同协议在不同层的传输过程!

  3. TCP网络协议通信原理(客户端和服务器端)

    下面直接用代码来说明TCP协议的基础知识: 服务器端代码块: from socket import * from time import ctime ''' 指定主机地址.工作端口号.接收缓存的长度 ...

  4. 网络协议之TCP

    前言 近年来,随着信息技术的不断发展,各行各业也掀起了信息化浪潮,为了留住用户和吸引用户,各个企业力求为用户提供更好的信息服务,这也导致WEB性能优化成为了一个热点.据分析,网站速度越快,用户的黏性. ...

  5. 网络协议HTTP TCP/UDP 浏览器缓存 Restful(十)

    一 TCP网络协议 1 建立TCP连接:三次握手原则 客户端通过向服务器端发送一个SYN来创建一个主动打开,作为三次握手的一部分.客户端把这段连接的序号设定为随机数 A. 服务器端应当为一个合法的SY ...

  6. 网络协议之TLS

    前言 由于在TCP.UDP等方式传输数据时,数据包有可能被其他人截获,并解析出信息,这就给信息安全带来了很大的挑战.最初的SSL协议被网景公司提出,它不会影响上层协议(如HTTP.电子邮件等),但可以 ...

  7. 网络协议之NAT穿透

    NAT IPv4地址只有32位,最多只能提供大致42.9亿个唯一IP地址,当设备越来越多时,IP地址变得越来越稀缺,不能为每个设备都分配一个IP地址.于是,作为NAT规范就出现了.NAT(Networ ...

  8. 网络协议之UDP

    前言 TCP协议在不可靠的网络环境上提供了可靠的通信通道,隐藏了大量的底层细节,使应用程序更加简洁.但有些应用并不需要这么高的可靠性,并不需要按序交付,而且TCP为了提高可靠性也增加了延时,在某些对延 ...

  9. TCP/IP协议(一)网络基础知识

    参考书籍为<图解tcp/ip>-第五版.这篇随笔,主要内容还是TCP/IP所必备的基础知识,包括计算机与网络发展的历史及标准化过程(简述).OSI参考模型.网络概念的本质.网络构建的设备等 ...

随机推荐

  1. centos 安装配置 mysql

    安装环境:CentOS7 64位 MINI版,安装MySQL5.7 1.配置YUM源 在MySQL官网中下载YUM源rpm安装包:http://dev.mysql.com/downloads/repo ...

  2. 老板怎么办,我们网站遭到DDoS攻击又挂了?

    相信现在正在阅读此文的你,一定听说过发生在上个月的史上最大的DDoS攻击. 美国东部时间2月28日,GitHub在一瞬间遭到高达1.35Tbps的带宽攻击.这次DDoS攻击几乎可以堪称是互联网有史以来 ...

  3. Mongodb 3 查询优化(慢查询Profiling)

    开启慢查询Profiling Profiling级别说明 0:关闭,不收集任何数据. 1:收集慢查询数据,默认是100毫秒. 2:收集所有数据 1.通过修改配置文件开启Profiling 修改启动mo ...

  4. 说说Java代理模式

    代理实现可以分为静态代理和动态代理. 静态代理 静态代理模式其实很常见,比如买火车票这件小事:黄牛相当于是火车站的代理,我们可以通过黄牛买票,但只能去火车站进行改签和退票.在代码实现中相当于为一个委托 ...

  5. istio入门(05)istio的架构概念2

  6. ELK学习总结(1-3)倒排索引

    1.倒排索引(反向索引) 一种索引方法,用来存储在全文检索下某个单词在一个/组文档中的存储位置. 常规索引,文档->关键词,费时,得把一个文档全部遍历一遍 倒排索引,关键词->文档,全文搜 ...

  7. Oracle 用户创建及权限设置

    1:创建临时表空间create temporary tablespace user_temp  tempfile 'D:\app\Administrator\oradata\ORACLE\xyrj_t ...

  8. HTNL表单详解

    HTML表单 表单的结构 表单的标签:<form> </form> 常用属性 Name , method(get,post), action(服务器的接收的页面如:reg.ph ...

  9. 服务器批量管理软件ansible安装以及配置

    1.yum安装(管理主机以及被管理主机都需要安装) yum install epel-release yum install ansible 2.配置管理主机 vim /etc/ansible/hos ...

  10. 学习React系列(五)——使性能最优

    提高性能可分为两方面: 一.配置层面 二.代码层面 本文只从代码层面考虑: 一.避免重复渲染 这里要说一句: 当shouldComponentUpdate返回false的时候不触发render函数也就 ...