2023河南萌新联赛第(二)场:河南工业大学 L题

线段树的题, 自己写了好久都没写出来, 就找了一个大神的模板。

#include <bits/stdc++.h>

const int N = 1e5+10;

typedef long long ll;

char s[N];
int n, q;

struct SegTree {
    struct Node {
        int l, r;
        int lenl, lenr;
        int maxlen, ld, rd;
    } tr[N<<2];
    
    void pushup(Node &root, Node &left, Node &right) {
        if(left.maxlen>=right.maxlen) {
            root.maxlen = left.maxlen;
            root.ld = left.ld, root.rd = left.rd; 
        }
        else {
            root.maxlen = right.maxlen;
            root.ld = right.ld, root.rd = right.rd; 
        }
        
        if(s[left.r]==s[right.l]) {
            if(left.lenr+right.lenl>root.maxlen||((left.lenr+right.lenl==root.maxlen)&&left.r-left.lenr+1<=root.ld)) {
                root.maxlen = left.lenr+right.lenl;
                root.ld = left.r-left.lenr+1;
                root.rd = right.l+right.lenl-1;
            }
        }
        
        if(left.lenl==(left.r-left.l+1)&&s[left.l]==s[right.l]) {
            root.lenl = left.lenl+right.lenl;
        }
        else {
            root.lenl = left.lenl;
        }
        
        if(right.lenr==(right.r-right.l+1)&&s[right.r]==s[left.r]) {
            root.lenr = right.lenr+left.lenr;
        }
        else {
            root.lenr = right.lenr;
        }
        
        if(root.lenl>=root.maxlen) {
            root.maxlen = root.lenl;
            root.ld = left.l, root.rd = left.l+root.lenl-1;
        }
        
        if(root.lenr>root.maxlen) {
            root.maxlen = root.lenr;
            root.rd = right.r, root.ld = right.r-root.lenr+1;
        }
    }
    
    void pushup(int u) {
        Node &root = tr[u], &left = tr[u<<1], &right = tr[u<<1|1];
        pushup(root,left,right);
    }
    
    void build(int u, int l, int r) {
        tr[u] = {l,r,1,1,1,l,r};
        if(l==r) return ;
        int mid = (l+r)>>1;
        build(u<<1,l,mid), build(u<<1|1,mid+1,r);
        pushup(u);
    }
    
    Node query(int u, int l, int r) {
        if(l<=tr[u].l&&tr[u].r<=r) return tr[u];
        
        int mid = (tr[u].l+tr[u].r)>>1;
        Node res = {tr[u].l,tr[u].r,0,0,0,0,0}, left = {tr[u].l,mid,0,0,0,0,0}, right = {mid+1,tr[u].r,0,0,0,0,0};
        if(l<=mid) left = query(u<<1,l,r);
        if(r>mid) right = query(u<<1|1,l,r);
//         if(r<=mid) return left;
//         if(l>mid) return right;
        pushup(res,left,right);
        return res;
    }
    
    void modify(int u, int x) {
        if(tr[u].l==tr[u].r) {
            return ;
        }
        
        int mid = (tr[u].l+tr[u].r)>>1;
        if(x<=mid) modify(u<<1,x);
        if(x>mid) modify(u<<1|1,x);
        pushup(u);
    }
} T;

void solve()
{
    std::cin >> n >> q >> (s+1);
    
    T.build(1,1,n);
    
    while(q --) {
        int op, l, r, x;
        char c;
        std::cin >> op;
        if(op==1) {
            std::cin >> l >> r;
            auto res = T.query(1,l,r);
            std::cout << res.ld << " " << res.rd << "\n";
        }
        else {
            std::cin >> x >> c;
            s[x] = c;
            T.modify(1,x);
        }
    }
}

signed main()
{
    std::ios::sync_with_stdio(false);
    std::cin.tie(0);
    
    int t = 1;
    while(t --)
        solve();
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值