The 1st Universal Cup. Stage 21: Shandong C. Connected Intervals

image

#include<iostream>
#include<vector>
#include<functional>
#include<cmath>
#include<queue>
#include<map>
#include<string>
#include<set>
#define int long long
#define inf 0x3f3f3f3f3f3f3f3f
#define TEST 
#define TESTS int _; std::cin >> _; while(_--)
struct node {
        int mx = -inf;
        int cnt = 0;
};
node operator+(const node& a, const node& b) {
        if(a.mx > b.mx) {
                return a;
        }
        else if(a.mx < b.mx) {
                return b;
        }
        else{
                return {a.mx, a.cnt + b.cnt};
        }
}
template<typename Info>
class SegmentTree {
public:
        explicit SegmentTree(int n): n_(n), tag_(4 * n, 0), info_(4 * n) {}
        /// 查询区间 [l, r)
        [[nodiscard]] Info query(int l, int r) {return query(1, 0, n_, l, r);}
        /// 区间加: 在 [l, r) 上全部加val
        void rangeAdd(int l, int r, int val) {rangeAdd(1, 0, n_, l, r, val);}
        /// 单点修改: 令 info[pos] = val
        void modify(int pos, const Info& val) {modify(1, 0, n_, pos, val);}
public:
        int n_;                         // 叶子数量
        std::vector<int> tag_;          // 懒标记数组
        std::vector<Info> info_;        // 节点信息数组
        inline void push_up(int p) {
                info_[p] = info_[p << 1] + info_[(p << 1) | 1];
        }
        inline void add(int p, int val) {
                tag_[p] += val;
                /// 额外节点信息修改, 例如:
                info_[p].mx += val;
        }
        void push_down(int p) {
                if(tag_[p] != 0) {
                        add(p << 1, tag_[p]);
                        add((p << 1) | 1, tag_[p]);
                        tag_[p] = 0;
                }
        }
        Info query(int p, int l, int r, int ql, int qr) {
                if(l >= qr or r <= ql) return Info{};
                if(l >= ql and r <= qr) return info_[p];
                int m = (l + r) >> 1;
                push_down(p);
                return query(p << 1, l, m, ql, qr) + query((p << 1) | 1, m, r, ql, qr);
        }
        void rangeAdd(int p, int l, int r, int ql, int qr, int val) {
                if(l >= qr or r <= ql) return;
                if(l >= ql and r <= qr) {add(p, val); return;}
                int m = (l + r) >> 1;
                push_down(p);
                rangeAdd(p << 1, l, m, ql, qr, val);
                rangeAdd((p << 1) | 1, m, r, ql, qr, val);
                push_up(p);
        }
        void modify(int p, int l, int r, int pos, const Info& val) {
                if(r - l == 1) {info_[p] = val; return;}
                int m = (l + r) >> 1;
                push_down(p);
                if(pos < m) modify(p << 1, l, m, pos, val);
                else modify((p << 1) | 1, m, r, pos, val);
                push_up(p);
        }
};
void Main() {
        int n;
        std::cin >> n;
        std::vector<std::vector<int> > adj(n);
        for(int i = 0; i < n - 1; ++i) {
                int u, v;
                std::cin >> u >> v;
                u--;
                v--;
                if(u < v) {
                        std::swap(u, v);
                }
                adj[u].push_back(v);
        }
        SegmentTree<node> seg(n);
        for(int i = 0; i < n; ++i) {
                seg.modify(i, {i, 1});
        }
        int ans = 0;
        for(int r = 0; r < n; ++r) {
                for(auto l: adj[r]) {
                        seg.rangeAdd(0, l + 1, 1);
                }
                ans += seg.query(0, r + 1).cnt;
                
                // for(int i = 0; i < n; ++i) {
                //         std::cout << seg.query(i, i + 1).mx << " \n"[i == n - 1];
                // }
        }
        std::cout << ans << "\n";
}
signed main() {
        std::ios::sync_with_stdio(false);
        std::cin.tie(nullptr);
        TESTS Main();
        return 0;
}

posted @ 2025-07-10 23:51  shen_kong  阅读(22)  评论(0)    收藏  举报