日常刷题

日常刷题

P1816 忠诚

rating:普及/提高-

https://www.luogu.com.cn/problem/P1816

思路(线段树)

标准的线段树板子题。

代码

#include <bits/stdc++.h>

using u64 = unsigned long long;
using i64 = long long;
typedef std::pair<int, int> pii;
const int INF = 0x3f3f3f3f;
const int mod = 998244353;
const long long LINF = 1e18;

struct Info{
    int min = INT_MAX;
};

Info operator+(const Info &a, const Info &b){
    if (a.min <= b.min){
        return a;
    }
    return b;
}

struct SegmentTree {
    int n;
    std::vector<int> tag;
    std::vector<Info> info; // 下标从 0 开始
    SegmentTree(int n_) : n(n_), tag(4 * n), info(4 * n) {}

	// 汇总信息
    void pull(int p) {
        info[p] = info[2 * p] + info[2 * p + 1];
    }

	//懒更新
    void add(int p, int v) {
        tag[p] += v;
        info[p].min += v;
    }

	// 把信息发下去
    void push(int p) {
        add(2 * p, tag[p]);
        add(2 * p + 1, tag[p]);
        tag[p] = 0;
    }
	// 查询是左闭右开的
    Info query(int p, int l, int r, int x, int y) {
        if (l >= y || r <= x) {
            return {};
        }
        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, r, x, y);
    }
    
    Info query(int x, int y) {
        return query(1, 0, n, x, y);
    }
	// 左闭右开
    void rangeAdd(int p, int l, int r, int x, int y, int v) {
        if (l >= y || r <= x) {
            return;
        }
        if (l >= x && r <= y) {
            return add(p, v);
        }
        int m = (l + r) / 2;
        push(p);
        rangeAdd(2 * p, l, m, x, y, v);
        rangeAdd(2 * p + 1, m, r, x, y, v);
        pull(p);
    }
    // 左闭右开
    void rangeAdd(int x, int y, int v) {
        rangeAdd(1, 0, n, x, y, v);
    }
	// 区间赋值
    void modify(int p, int l, int r, int x, const Info &v) {
        if (r - l == 1) {
            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, r, x, v);
        }
        pull(p);
    }
    
    void modify(int x, const Info &v) {
        modify(1, 0, n, x, v);
    }
};

void solve(){
    int n, m;
    std::cin >> n >> m;

    std::vector<int> a(n);
    for (int i = 0; i < n; i++) std::cin >> a[i];

    SegmentTree stree(n);

    for (int i = 0; i < n; i++){
        stree.modify(i, {a[i]});
    }

    while (m--){
        int l, r;
        std::cin >> l >> r;
        l--;
        int ret = stree.query(l, r).min;
        std::cout << ret << ' ';
    }
    std::cout << '\n';
}

signed main(){
    std::ios::sync_with_stdio(false);
    std::cin.tie(nullptr);
    std::cout<<std::setiosflags(std::ios::fixed)<<std::setprecision(15);

    int t = 1, i;
    for (i = 0; i < t; i++){
        solve();
    }

    return 0;
}

智乃的小球

rating:1400

https://ac.nowcoder.com/acm/contest/95335/E

思路:二分答案

时间越多可能发生的碰撞越多,具有明显的单调性,并且在知道时间的情况下容易计算出碰撞次数,所以这是一道标准的二分答案

代码

#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>

using namespace std;

const int INF = 1000000001;

long long count_pairs(long long t, vector<long long> &u, vector<long long> &v)
{
    long long result = 0;
    int p1 = 0, p2 = 0;
    for (auto &i: u)
    {
        while (p2 < v.size() && v[p2] < i)++p2;
        while (p1 < v.size() && v[p1] <= i + t)++p1;
        result += p1 - p2;
    }
    return result;
}

int main()
{
    int n;
    long long k;

    scanf("%d %lld", &n, &k);
    vector<long long> u, v;
    for (int i = 0; i < n; ++i)
    {
        long long x, y;
        scanf("%lld %lld", &x, &y);
        if (y == 1)
        {
            u.push_back(x);
        } else
        {
            v.push_back(x);
        }
    }

    sort(u.begin(), u.end());
    sort(v.begin(), v.end());
    int l = 0, r = INF, ans = 0;
    while (l <= r)
    {
        int mid = (l + r) / 2;
        auto nowk = count_pairs(mid, u, v);
        if (nowk >= k)
        {
            r = mid - 1;
        } else
        {
            ans = mid;
            l = mid + 1;
        }
    }
    if (ans == INF)
    {
        printf("No\n");
        return 0;
    }
    ans++;
    printf("Yes\n%d.%c00000\n", ans / 2, "05"[ans & 1]);
    return 0;
}


posted @ 2025-02-01 10:59  califeee  阅读(16)  评论(0)    收藏  举报