首页 > 其他分享 >10.22 树状数组

10.22 树状数组

时间:2024-10-22 13:45:07浏览次数:1  
标签:Info info 10.22 return 数组 树状 int init &&

https://codeforces.com/contest/1838/problem/D
都在代码里了
const int INF = 1e9;
struct Info{//定义一个结构体
int mn;
Info() : mn(INF) {}//调用这个自定义函数就把mn变成极大值
Info(int mn) : mn(mn) {}//调用这个自定义函数就把mn变成你输入的值
};

using Tag = int;

Info operator+(const Info &a, const Info &b){//排序
return {min(a.mn, b.mn)};
}

void apply(Info &x, Tag &a, Tag f){
x.mn += f;
a += f;
}

template<class Info, class Tag>
struct LazySegmentTree{
int n;
vector info;//树状数组
vector tag;//懒标记

LazySegmentTree() {}

LazySegmentTree(int n, Info _init = Info()){
    init(vector<Info>(n, _init));
}

LazySegmentTree(const vector<Info> &_init){
    init(_init);
}

void init(const vector<Info> &_init){//建立树状数组
    n = (int)_init.size();
    info.assign((n << 2) + 1, Info());
    tag.assign((n << 2) + 1, Tag());
    function<void(int, int, int)> build = [&](int p, int l, int r){
        if (l == r){
            info[p] = _init[l - 1];
            return;
        }
        int m = (l + r) / 2;
        build(2 * p, l, m);
        build(2 * p + 1, m + 1, r);
        pull(p);
    };
    build(1, 1, n);
}

void pull(int p){
    info[p] = info[2 * p] + info[2 * p + 1];
}

void apply(int p, const Tag &v){
    ::apply(info[p], tag[p], v);
}

void push(int p){
    apply(2 * p, tag[p]);
    apply(2 * p + 1, tag[p]);
    tag[p] = Tag();
}

void modify(int p, int l, int r, int x, const Info &v){//区间变值
    if (l == r){
        info[p] = v;
        return;
    }
    int m = (l + r) / 2;
    push(p);
    if (x <= m){
        modify(2 * p, l, m, x, v);
    } 
    else{
        modify(2 * p + 1, m + 1, r, x, v);
    }
    pull(p);
}

void modify(int p, const Info &v){//单点变值
    modify(1, 1, n, p, v);
}

Info query(int p, int l, int r, int x, int y){
    if (l > y || r < x){
        return Info();
    }
    if (l >= x && r <= y){
        return info[p];
    }
    int m = (l + r) / 2;
    push(p);
    return query(2 * p, l, m, x, y) + query(2 * p + 1, m + 1, r, x, y);
}

Info query(int l, int r){
    return query(1, 1, n, l, r);
}

void modify(int p, int l, int r, int x, int y, const Tag &v){
    if (l > y || r < x){
        return;
    }
    if (l >= x && r <= y){
        apply(p, v);
        return;
    }
    int m = (l + r) / 2;
    push(p);
    modify(2 * p, l, m, x, y, v);
    modify(2 * p + 1, m + 1, r, x, y, v);
    pull(p);
}

void modify(int l, int r, const Tag &v){
    return modify(1, 1, n, l, r, v);
}

int find_first(int p, int l, int r, int L, int R, const function<bool(const Info&)> &f, Info &pre){
    if (l > R || r < L){
        return r + 1;
    }
    if (l >= L && r <= R){
        if (!f(pre + info[p])){
            pre = pre + info[p];
            return r + 1;
        }
        if (l == r) return r;
        int m = (l + r) / 2;
        push(p);
        int res;
        if (f(pre + info[2 * p])){
            res = find_first(2 * p, l, m, L, R, f, pre);
        }
        else{
            pre = pre + info[2 * p];
            res = find_first(2 * p + 1, m + 1, r, L, R, f, pre);
        }
        return res;
    }
    int m = (l + r) / 2;
    push(p);
    int res = m + 1;
    if (L <= m){
        res = find_first(2 * p, l, m, L, R, f, pre);
    }
    if (R > m && res == m + 1){
        res = find_first(2 * p + 1, m + 1, r, L, R, f, pre);
    }
    return res;
}

int find_first(int l, int r, const function<bool(const Info&)> &f){//找到第一个满足条件的(加一个自己设置的函数)
    Info pre = Info();
    return find_first(1, 1, n, l, r, f, pre);
}

int find_last(int p, int l, int r, int L, int R, const function<bool(const Info&)> &f, Info &suf){
    if (l > R || r < L){
        return l - 1;
    }
    if (l >= L && r <= R){
        if (!f(info[p] + suf)){
            suf = info[p] + suf;
            return l - 1;
        }
        if (l == r) return r;
        int m = (l + r) / 2;
        push(p);
        int res;
        if (f(info[2 * p + 1] + suf)){
            res = find_last(2 * p + 1, m + 1, r, L, R, f, suf);
        }
        else{
            suf = info[2 * p + 1] + suf;
            res = find_last(2 * p, l, m, L, R, f, suf);
        }
        return res;
    }
    int m = (l + r) / 2;
    push(p);
    int res = m;
    if (R > m){
        res = find_last(2 * p + 1, m + 1, r, L, R, f, suf);
    }
    if (L <= m && res == m){
        res = find_last(2 * p, l, m, L, R, f, suf);
    }
    return res;        
}

int find_last(int l, int r, const function<bool(const Info&)> &f){//找到最后一个满足条件的(加一个自己设置的函数)
    Info suf = Info();
    return find_last(1, 1, n, l, r, f, suf);
}

};

void solve()
{
int n,q;
cin>>n>>q;
string s;
vector init(n);
sets1,s2;
cin>>s;
s=" "+s+" ";
int sum=0;
if(n%2)
{
while(q--)
{
int x;
cin>>x;
cout<<"NO"<<endl;
}
}
for(int i=1;i<=n;i++)
{
if(s[i]'(' && s[i-1]'(') s1.insert(i-1);
if(s[i]')' && s[i-1]')') s2.insert(i-1);
if(s[i]'(') sum++;
else sum--;
init[i-1]={sum};//init里全部是前缀和
}
LazySegmentTree<Info, Tag> seg(init);//建树 自定义了树的名字叫做seg
while(q--)
{
int x;
cin>>x;
if(s[x]
'(' && s[x-1]'(') s1.erase(x-1);
if(s[x]
'(' && s[x+1]'(') s1.erase(x);
if(s[x]
')' && s[x-1]')') s2.erase(x-1);
if(s[x]
')' && s[x+1]==')') s2.erase(x);

    if(s[x]=='(') 
    {
        s[x]=')';
        sum-=2;
        seg.modify(x,n,-2);
    }
    else
    {
        s[x]='(';
        sum+=2;
        seg.modify(x,n,2);
    }

    if(s[x]=='(' && s[x-1]=='(') s1.insert(x-1);
    if(s[x]=='(' && s[x+1]=='(') s1.insert(x);
    if(s[x]==')' && s[x-1]==')') s2.insert(x-1);
    if(s[x]==')' && s[x+1]==')') s2.insert(x);
    
    auto f1 = [&](const Info &info){//自己写一个内置函数判断
        return info.mn < 0;//这里前面肯定出现了连续的')' 
    };

    auto f2 = [&](const Info &info){
        return info.mn < sum;//这里后面肯定出现了连续的'('
    };

    int pos1=seg.find_first(1,n,f1);
    int pos2=seg.find_last(1,n,f2);
    bool ok=1;
    if(pos1!=n+1)//找到了
    {
        auto it=s1.lower_bound(pos1);
        if(it==s1.begin()) ok=0;//只要第一个大于pos1(不可能等于嘛)不是第一个数 就意味着前面还有合法点
    }
    if(pos2!=0)//找到了
    {
        auto it=s2.lower_bound(pos2);
        if(it==s2.end()) ok=0;
    }
    if(ok) cout<<"YES"<<endl;
    else cout<<"NO"<<endl;
}

}

标签:Info,info,10.22,return,数组,树状,int,init,&&
From: https://www.cnblogs.com/d-p-n-i-/p/18492493

相关文章

  • VBA中用range生成的行数组或列数组均为二维数组,转成一维方法
    在excel中用range方法生成的行或列数组均为二维数组,1、行数组。如arr=sheet1.range("a1:c1"),这是一行三列的二维数组,用arr(1,1)、arr(1,2)、arr(1,3)均能获取数据,但如用arr(1)、arr(2)、arr(3)获取数组就会出错,提示“下标越界",若用arr(1,1)就会取到数据,所以用range生成的行数......
  • 华为od面试手撕代码真题题型1——常规字符串,数组,矩阵
    常规字符串,数组,矩阵1实现超长数字减1思路:Java中用BigInteger类publicStringsubOne(Strings){ BigIntegerbi=newBigInteger(s);bi=bi.subtract(BigInteger.ONE);returnbi.toString();}2十八进制数比较大小任意进制的字符串a,转成十进制的数:In......
  • 将有序数组转换为二叉搜索树
    给你一个整数数组 nums ,其中元素已经按 升序 排列,请你将其转换为一棵 平衡 二叉搜索树。示例1:输入:nums=[-10,-3,0,5,9]输出:[0,-3,9,-10,null,5]解释:[0,-10,5,null,-3,null,9]也将被视为正确答案:示例2:输入:nums=[1,3]输出:[3,1]解释:[1,null,3]和[3......
  • Day21数组的声明和创建
    Day21数组的声明和创建数组声明创建:首先必须声明数组变量才能在程序中使用数组。声明数组变量的语法有两种:“dataType[]arrayRefVar;”(首选方法);或“dataTypearrayRefVar[];”(效果相同,但不是首选方法)。Java语言使用new操作符来创建数组,语法为dataType[]arra......
  • 数组的概念(C++)
        今天介绍一下数组。在C++中,数组就是一种用于存储相同类型元素的容器,也是一种数据结构,在编程中被广泛使用。一、定义与组成    数组是由相同类型的元素组成的集合,这些元素在内存中是连续存储的。例如,一个整数数组可以存储多个整数,一个字符数组可以存储......
  • 【java】实现字节数组转int(采用IEEE 754标准)
    /***字节数组转int*采用IEEE754标准**@parambytes*@returnfloat*/publicintbytesToInt(byte[]bytes){//获取字节数组转化成的2进制字符串StringbinaryStr=bytesToBinaryStr(bytes);//......
  • 代码随想录算法训练营第六天| leetcode242.有效的字母异位词、leetcode349.两个数组的
    1.leetcode242.有效的字母异位词题目链接:242.有效的字母异位词-力扣(LeetCode)文章链接:代码随想录视频链接:学透哈希表,数组使用有技巧!Leetcode:242.有效的字母异位词_哔哩哔哩_bilibili自己的思路:首先就是对字符串进行分开成一个一个单独的字母,然后使用列表存储这些数据,再对......
  • 数组的往返(数组来回遍历)C语言版
    文章目录前言题目描述一、数组的往返是什么?二、实现1.具体代码2.完整题解代码总结以及一些疑问前言本篇文章灵感来源于第十三届蓝桥杯省赛C++B组第六题修剪灌木,我的方法是老老实实地走完这个流程得到答案题目描述爱丽丝要完成一项修剪灌木的工作。有N棵灌......
  • 包装类型-数组Array方法
    数组Array使用详解认识数组(Array)◼什么是数组(Array)呢?对象允许存储键值集合,但是在某些情况下使用键值对来访问并不方便;比如说一系列的商品、用户、英雄,包括HTML元素,我们如何将它们存储在一起呢?这个时候我们需要一种有序的集合,里面的元素是按......
  • JS中数组的splice()方法介绍 及 用原生JS手写数组splice()方法
    一、splice是什么splice()方法是用来对数组进行增、删操作,该方法返回被删除的元素,改变原数组二、splice()方法接受三个及以上的参数:第一个参数:第一个参数是起始位置(数组的索引)第二个参数:第二个参数是要删除的元素个数,如果该参数是负数则默认为0第三个参数及往后参数:这些......