第十七届同济大学程序设计预选赛H

时空栈

https://ac.nowcoder.com/acm/contest/5477/H

我们不妨将入栈操作看作在这个时间点加1,将出栈操作看作这个时间点-1。那么询问当前时间点的栈顶元素就是找到最大的后缀下标使得这个后缀的和是1即可。
我们通过线段树来维护区间后缀值,维护时,需要同时维护这个区间和以及后缀最大值。如果采用是自底向上的线段树即zkw线段树,那么query只要一个函数即可。如果采用常规的自顶向下的线段树,需要先找的合法的右端点,然后找到合法的区间用第二个query来查找答案。

代码:

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <stack>
using namespace std;

#define lson rt * 2
#define rson rt * 2 + 1

const int N = 2e5 + 100;

struct node {
    int sum, ma;
    node() {
        sum = ma = 0;
    }
    void set(int x) {
        sum = ma = x;
    }
}sa[N * 4];

node cal(node a, node b) {
    node c;
    c.sum = a.sum + b.sum;
    c.ma = max(a.ma + b.sum, b.ma);
    return c;
}

int n, tp;
int op[N], aa[N], bb[N], has[N], rev[N];

void insert(int id, int l, int r, int rt) {
    if (l == r) {
        int i = rev[l];
        if (op[i] == 0) sa[rt].set(1);
        else sa[rt].set(-1);
        return;
    }
    int m = (l + r) / 2;
    if (id <= m) insert(id, l, m, lson);
    else insert(id, m + 1, r, rson);
    sa[rt] = cal(sa[lson], sa[rson]);
}

int res;

void query(node x, int l, int r, int rt) {
    if (l == r) {
        res = bb[rev[l]];
        return;
    }
    int m = (l + r) / 2;
    if (cal(sa[rson], x).ma > 0) query(x, m + 1, r, rson);
    else query(cal(sa[rson], x), l, m, lson);
}

void query(int id, node &x, int l, int r, int rt) {
    if (l == r) {
        x = sa[rt];
        if (sa[rt].sum > 0) query(x, l, r, rt);
        return;
    }
    int m = (l + r) / 2;
    if (id <= m) {
        query(id, x, l, m, lson);
    }
    else {
        query(id, x, m + 1, r, rson);
        if (!res) {
            if (cal(sa[lson], x).ma > 0) {
                query(x, l, m, lson);
            }
            x = cal(sa[lson], x);
        }
    }
}

int main() {
    //freopen("0.txt", "r", stdin);
    scanf("%d", &n);
    for (int i = 1; i <= n; i++) {
        scanf("%d", op + i);
        if (op[i]) scanf("%d", aa + i);
        else scanf("%d%d", aa + i, bb + i);
        has[++tp] = i;
    }
    sort(has + 1, has + 1 + tp);
    tp = unique(has + 1, has + 1 + tp) - has;
    for (int i = 1; i <= n; i++) {
        aa[i] = lower_bound(has + 1, has + tp, aa[i]) - has;
        if (op[i] != 2) rev[aa[i]] = i;
    }
    for (int i = 1; i <= n; i++) {
        if (op[i] == 2) {
            res = 0;
            node x;
            query(aa[i], x, 1, tp, 1);
            printf("%d\n", res);
        }
        else insert(aa[i], 1, tp, 1);
    }
    return 0;
}
全部评论

相关推荐

压力很大,面试官全程高压,问的问题不难,但是没有任何反馈,很慌张,也无算法。实习问了20分钟,一直问我你们做的有什么用,总时长一小时1.学校都有什么课程2.spring的ioc原理以及优点3.除了解耦还知道什么?4.springboot与spring区别,二者的源码看过没?Tomcat了解嘛?有没有具体看过5.spring的bean,面试官一直在重复一个思想问我懂不懂,完全没听过6.mybatis是干什么的?ibatis用过没?平常怎么写SQL?完全不写嘛?7.设计一个分布式双十一秒杀系统(前端,网关,缓存,数据库防超卖全设计)8.怎么做限流9.缓存与数据库一致性,你做异步要用户等你嘛?10.负载均衡怎么做11.多数据中心还是单数据中心,如果出现没卖完怎么做(到这完全不会了,面试官直接说换个话题吧)12.平常读书吗?13.上过哲学课嘛?14.兴趣爱好有没有15.对ai的看法16.来深圳有问题嘛?17.为什么不考研18.上大学带给了你什么?你提升在哪里,有没有具体的例子?反问:1.现在手机都有应用市场,应用宝怎么盈利?除了手机应用市场还是有人用,现在在做跨端,微软都有合作,之后会进军mac,主要做游戏,腾讯本身就是游戏大户。2.面试表现?整体评价一下会给到反馈。面完直接变HR面,今天HR面后,已经转为录用评估了,来牛客许个愿,暑期现在还没什么面试,希望能拿个offer之后再考虑要不要留在手子吧。
nunuking:三面压力这么大吗,面试的会议约了多长时间呀
面试问题记录
点赞 评论 收藏
分享
评论
2
收藏
分享

创作者周榜

更多
正在热议
更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务