当前位置: 首页 > news >正文

uestc 94(区间更新)

题意:有一个字符串全部由’(‘和’)’组成。然后有三种操作,query a b输出区间[a,b]字符串的括号序列是否合法。reverse a b把区间[a,b]字符串里全部’(‘替换成’)’,而且把全部’)’替换为’(‘,set a b c,把区间[a,b]的全部字符替换为c。
题解:明显是线段树,为了能够让线段树维护,推断一个字符串是否为合法括号,能够把全部的’(‘替换为-1,’)’替换为1,那么假设这个字符串合法,整个字符串的和应该是0且前缀最大和不能超过0。所以能够在线段树节点加入maxx和sum这两个值维护区间内的前缀最大和和总和。

然后reverse操作时。为了方便计算maxx,节点应该还要维护minn前缀最小和,这样maxx = -minn能够直接计算。还有区间合并时最大和是选左子区间最大和与左子区间总和加上右子区间的最大和中较大的那个。最小和求法同理。

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 100005;
struct Tree {
    int sum, maxx, minn;
    int setv, rev;
    void f(int val, int left, int right) {
        if (!val) {
            sum = -sum;
            int temp = maxx;
            maxx = -minn;
            minn = -temp;
            rev ^= 1;
        }
        else {
            minn = min(val, val * (right - left + 1));  
            maxx = max(val, val * (right - left + 1));
            sum = val * (right - left + 1);
            setv = val;
            rev = 0;
        }
    }
}tree[N << 2];
int n, q, a[N];
char s[N], op[10], c[5];

void pushdown(int k, int left, int right) {
    int mid = (left + right) / 2;
    if (tree[k].setv) {
        tree[k * 2].f(tree[k].setv, left, mid);
        tree[k * 2 + 1].f(tree[k].setv, mid + 1, right);
        tree[k].setv = 0;
    }
    if (tree[k].rev) {
        tree[k * 2].f(0, left, mid);
        tree[k * 2 + 1].f(0, mid + 1, right);
        tree[k].rev = 0;
    }
}

void pushup(int k) {
    tree[k].sum = tree[k * 2].sum + tree[k * 2 + 1].sum;
    tree[k].maxx = max(tree[k * 2].maxx, tree[k * 2].sum + tree[k * 2 + 1].maxx);
    tree[k].minn = min(tree[k * 2].minn, tree[k * 2].sum + tree[k * 2 + 1].minn);
}

void build(int k, int left, int right) {
    tree[k].setv = tree[k].rev = 0;
    if (left == right) {
        tree[k].sum = tree[k].maxx = tree[k].minn = a[left];
        return;
    }
    int mid = (left + right) / 2;
    build(k * 2, left, mid);
    build(k * 2 + 1, mid + 1, right);
    pushup(k);
}

void modify(int k, int left, int right, int l, int r, int v) {
    if (l <= left && right <= r) {
        tree[k].f(v, left, right);
        return;
    }
    pushdown(k, left, right);
    int mid = (left + right) / 2;
    if (l <= mid)
        modify(k * 2, left, mid, l, r, v);
    if (r > mid)
        modify(k * 2 + 1, mid + 1, right, l, r, v);
    pushup(k);
}

void query(int k, int left, int right, int l, int r, int &sum, int &maxx) {
    if (l <= left && right <= r) {
        maxx = tree[k].maxx;
        sum = tree[k].sum;
        return;
    }
    pushdown(k, left, right);
    int mid = (left + right) / 2;
    if (r <= mid)
        query(k * 2, left, mid, l, r, sum, maxx);
    else if (l > mid)
        query(k * 2 + 1, mid + 1, right, l, r, sum, maxx);
    else {
        int sum1, maxx1, sum2, maxx2;
        query(k * 2, left, mid, l, mid, sum1, maxx1);
        query(k * 2 + 1, mid + 1, right, mid + 1, r, sum2, maxx2);
        sum = sum1 + sum2;
        maxx = max(maxx1, sum1 + maxx2);
    }
    pushup(k);
}

int main() {
    int t, cas = 1;
    scanf("%d", &t);
    while (t--) {
        scanf("%d%s", &n, s + 1);
        for (int i = 1; i <= n; i++)
            if (s[i] == '(')
                a[i] = -1;
            else
                a[i] = 1;
        build(1, 1, n);
        printf("Case %d:\n", cas++);
        scanf("%d", &q);
        int l, r, sum, maxx;
        while (q--) {
            scanf("%s", op);
            if (op[0] == 'q') {
                scanf("%d%d", &l, &r);
                query(1, 1, n, l + 1, r + 1, sum, maxx);
                if (!sum && maxx <= 0)
                    printf("YES\n");
                else
                    printf("NO\n");
            }
            else if (op[0] == 's') {
                scanf("%d%d%s", &l, &r, c);
                if (c[0] == '(')
                    modify(1, 1, n, l + 1, r + 1, -1);
                else
                    modify(1, 1, n, l + 1, r + 1, 1);
            }
            else {
                scanf("%d%d", &l, &r);
                modify(1, 1, n, l + 1, r + 1, 0);
            }
        }
        printf("\n");
    }
    return 0;
}

相关文章:

  • 使用HSRP和OSPF实现网络冗余
  • 《Java实战开发经典》第五章5.3
  • MongoDB数据库操作和程序基础文档
  • Java网络编程与NIO详解11:Tomcat中的Connector源码分析(NIO)
  • C# 正则移除所有的Html标记
  • PHP页面3中跳转方法
  • RTEMS 的小技巧(2011.6.30.)
  • 程序猿爱情表白专用html5动画网页的代码
  • 一次ARP问题的Troubleshooting
  • XMPP添加删除好友
  • SQL Server 2008 Analysis Service第二回
  • Spring Security入门(3-3)Spring Security 手工配置并注入 authenticationProvider 和 异常信息传递...
  • 二十二、二十三天笔记总结
  • How to install nokogiri
  • 微信JS 关闭网页
  • 8年软件测试工程师感悟——写给还在迷茫中的朋友
  • Dubbo 整合 Pinpoint 做分布式服务请求跟踪
  • ES学习笔记(10)--ES6中的函数和数组补漏
  • go语言学习初探(一)
  • LeetCode29.两数相除 JavaScript
  • Python打包系统简单入门
  • Redux 中间件分析
  • vue学习系列(二)vue-cli
  • 对超线程几个不同角度的解释
  • 分布式熔断降级平台aegis
  • 工程优化暨babel升级小记
  • 关于Android中设置闹钟的相对比较完善的解决方案
  • 基于HAProxy的高性能缓存服务器nuster
  • 浏览器缓存机制分析
  • 排序(1):冒泡排序
  • 我从编程教室毕业
  • 我建了一个叫Hello World的项目
  • 一份游戏开发学习路线
  • 移动端解决方案学习记录
  • 中国人寿如何基于容器搭建金融PaaS云平台
  • 从如何停掉 Promise 链说起
  • ​LeetCode解法汇总2583. 二叉树中的第 K 大层和
  • ​批处理文件中的errorlevel用法
  • #周末课堂# 【Linux + JVM + Mysql高级性能优化班】(火热报名中~~~)
  • (2022 CVPR) Unbiased Teacher v2
  • (31)对象的克隆
  • (6)设计一个TimeMap
  • (M)unity2D敌人的创建、人物属性设置,遇敌掉血
  • (附源码)springboot炼糖厂地磅全自动控制系统 毕业设计 341357
  • (附源码)小程序儿童艺术培训机构教育管理小程序 毕业设计 201740
  • (已更新)关于Visual Studio 2019安装时VS installer无法下载文件,进度条为0,显示网络有问题的解决办法
  • (转)我也是一只IT小小鸟
  • .NET 3.0 Framework已经被添加到WindowUpdate
  • .NET/C# 编译期间能确定的相同字符串,在运行期间是相同的实例
  • .NET/C# 使窗口永不激活(No Activate 永不获得焦点)
  • .NetCore部署微服务(二)
  • .vue文件怎么使用_vue调试工具vue-devtools的安装
  • @JSONField或@JsonProperty注解使用
  • @RestControllerAdvice异常统一处理类失效原因
  • [ solr入门 ] - 利用solrJ进行检索