【TCP网络协议问题】

题目描述

在如今的网络中,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的时间点,但这样时间会爆炸)

#include<stdio.h>
#include<algorithm>
#define go(i,a,b) for(int i=a;i<=b;i++)
using namespace std;const int N=300004;
struct TCP{char act;int Num,tim;}g[N];
int n,Table[N],t,root,sz,list[N],k,Ll[N],Rr[N],ans;
int lch[N*4],rch[N*4],sum[N*4],suffix[N*4],num[N];
void build(int& u,int l,int r){u=++sz;if(l==r)return;int mid=l+r>>1;
     build(lch[u],l,mid);build(rch[u],mid+1,r);}
void update(int u,int l,int r,int P,int val)
{
    if(l==r){suffix[u]=sum[u]=val;return;}int mid=l+r>>1;
    P<=mid?update(lch[u],l,mid,P,val):update(rch[u],mid+1,r,P,val);
    sum[u]=sum[lch[u]]+sum[rch[u]];
    suffix[u]=max(suffix[lch[u]]+sum[rch[u]],suffix[rch[u]]);
}
void divide(int u,int l,int r,int L,int R)
{
    if(l==L&&r==R){list[++k]=u;Ll[k]=l;Rr[k]=r;return;}
    int mid=l+r>>1;if(R<=mid)divide(lch[u],l,mid,L,R);
    else if(mid<L)divide(rch[u],mid+1,r,L,R);
    else divide(rch[u],mid+1,r,mid+1,R),
         divide(lch[u],l,mid,L,mid);
}
void dichotomy(int u,int l,int r,int tmp)
{
    while(l<r){int mid=l+r>>1;
    if(tmp+suffix[rch[u]]>0)u=rch[u],l=mid+1;
    else tmp+=sum[rch[u]],u=lch[u],r=mid;}ans=num[l];
}
int main()
{
    scanf("%d",&n);char s[5];int x,y;
    go(i,1,n)x=0,scanf("%s",s+1),s[2]==‘u‘?scanf("%d%d",&x,&y):scanf("%d",&y),
    g[i]=(TCP){s[2],x,y},Table[++t]=y;sort(Table+1,Table+t+1);
    go(i,1,n)g[i].tim=lower_bound(Table+1,Table+t+1,g[i].tim)-Table;

    build(root,1,t);
    go(i,1,n)
    {
        if(g[i].act==‘u‘)update(1,1,t,g[i].tim, 1),num[g[i].tim]=g[i].Num;
        if(g[i].act==‘o‘)update(1,1,t,g[i].tim,-1);
        if(g[i].act==‘e‘)
        {
            k=0;bool get_ans=0;int suffix_tot=0;
            divide(1,1,t,1,g[i].tim);
            go(j,1,k)if(suffix_tot+suffix[list[j]]>0)
            {
                dichotomy(list[j],Ll[j],Rr[j],suffix_tot);
                get_ans=1;printf("%d\n",ans);break;
            }
            else suffix_tot+=sum[list[j]];
            if(!get_ans)printf("-1\n");
        }
    }
    return 0;
}//Paul_Guderian

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

时间: 2024-10-21 20:39:26

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

TCP网络协议的三次握手及代码释义

讲解TCP协议,我们首先要了解什么是网络通讯协议. 1.网络通讯协议 两台计算机要想在网络中互相通讯,就必须要遵守一定的规定,并且只有通讯双方同时遵守了这些规定,才能够实现数据的相互传输.而这些规定,便是由网络通讯协议针对数据传输格式,传输速率,传输步骤等制定的. 2.网络协议分类 java.net 包中包含的类和接口,它们提供低层次的通信细节,其中包含了两种常见的网络协议的支持: 1)TCP(Transmission Control Protocal) 即传输控制协议,TCP协议是面向连接的通

TCP网络协议

两个主机中间的通信 两个主机之间的通信是一个主机的进程与另一个主机的进程在交换数据,IP协议只是把数据包文传输到目的主机,但并没有交付给目的主机的具体应用进程.只有端到端的通信才是真正的应用进程之间的通信 TCP概述 TCP把链接作为最基础的对象,每一条TCP链接都有两个端点,端点也叫作套接字,套接字的定义为:IP地址拼接端口号,如:192.168.77.91:8080. TCP报文关键首部 序号,占4个字节,TCP连接中传输的字节流中每个字节都按顺序编号.例如一个报文的序号字段是301,而其携

Android网络编程系列 一 TCP/IP协议族

在学习和使用Android网路编程时,我们接触的仅仅是上层协议和接口如Apache的httpclient或者Android自带的httpURlconnection等等.对于这些接口的底层实现我们也有必要进一步的了解,这就要我们了解网络通信层了,提到网络通信层不得不说起ISO-OSI的七层协议经典架构,如图所示: 上图的左边部分就是osi架构模型了, ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是国际标

TCP/IP网络协议

什么是协议?协议就是双方约定的规则.同理,在网络中,计算机之间的相互通信需要共同遵守一定的规则,这些规则就称为网络协议. 下面是我百度的定义: TCP/IP是“transmission Control Protocol/Internet Protocol”的简写,中文译名为传输控制协议/互联网络协议)协议, TCP/IP(传输控制协议/网间协议)是一种网络通信协议,它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据往来格式以及传送方式.TCP/IP是INTERNET的基础协议,也

加域报错:“TCP/IP没有安装网络协议”

检查电脑后发现问题: 1.电脑不能自动获取IP地址 2.手动设置IP地址后加域报错 估计TCP/IP协议损坏,重新安装即可解决:以下为重装TCP/IP协议方法: 1.打开注册表编辑器,删除以下两个键: HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Winsock HKEY_LOCAL_MACHINE\System\CurrentControlSet\Services\Winsock2 2.用记事本打开%winroot%\inf\nett

基于 TCP/IP 协议的网络编程

在说明基于 TCP/IP 协议的网络编程之前,先来了解一下 Socket(网络套接字): 利用套接字(Socket)开发网络应用程序早已被广泛的采用,以至于成为事实上的标准 通信的两端都要有 Socket,是两台机器间通信的端点(API 原话) 网络通信其实就是 Socket 间的通信 Socket 允许程序把网络连接当成一个流,数据在两个 Socket 间通过 IO 传输 一般主动发起通信的应用程序属客户端,等待通信请求的为服务端 网络编程某种程度上可以称作"Socket 编程" T

Android网络编程系列 一 TCP/IP协议族之链路层

这篇借鉴的文章主要是用于后续文章知识点的扩散,在此特作备份和扩散学习交流. 数据链路层有三个目的: 为IP模块发送和 接收IP数据报. 为ARP模块发送ARP请求和接收ARP应答. 为RARP发送RARP请 求和接收RARP应答 ip大家都听说过.至于ARP和RARP,ARP叫做地址解析协议,是用IP地址换MAC地址的一种协议,而RARP则叫做逆地址解析协议,在tcp/ip协议的后面章节会介绍它们(在局域网里面用ARP协议可以很容易的搞瘫痪网络哦) 数据链路层的协议还是很多的,有我们最常用的以太

Android网络编程系列 一 TCP/IP协议族之网际层

这篇借鉴的文章主要是用于后续文章知识点的扩散,在此特作备份和扩散学习交流. 网际层包括:IP.ICMP.IGMP 以及处在网际层实际工作在链路层的 ARP 和 RARP等等协议. 1.IP协议 互联网上的每个接口必须有一个唯一的Internet地址(也称作IP地址).IP地址长32 bit.IP协议是TCP/IP协议的核心,所有的TCP,UDP,ICMP,IGMP的数据都以IP数据格式传输.要注意的是,IP不是可靠的协议,这是说,IP协议没有提供一种数据未传达以后的处理机制--这被认为是上层协议

【网络协议】TCP的拥塞控制机制

前言 计算机网络中的带宽.交换节点中的缓存和处理机等,都是网络的资源,在某段时间内,若对网络中某一资源的需求超过了该资源所能提供的可用部分,网络的性能就要变坏,这样的情况就叫做拥塞. 所谓拥塞控制,就是防止过多的数据注入到网络中,从而使网络中的路由器或链路不致过载.要注意用拥塞控制与流量控制的差别,拥塞控制是一个全局性的过程,涉及到全部的额主机.路由器,以及与减少网 拥塞控制的算法有:慢開始.拥塞避免.快重传.快恢复四种. 慢開始和拥塞避免 发送方维持一个拥塞窗体的状态变量,其大小取决于网络的拥