B -- RE:从零开始的异世界生活 线段树

http://www.ifrog.cc/acm/problem/1117?contest=1016&no=1

其实我是第一次这样用线段树。

首先把所有出现过的数字全部离散化。那么数字就是从[1,  100000]了。

把他们看成一个个独立的节点。每次插入一个数字,就在那个位置加1.

那么线段树维护区间总和,想知道小于x的数字有多少个,直接区间查询[1, x - 1]即可。

如果把小于x的数,变成x,相当于把[1, x - 1]中出现了多少个数字,贡献 add 到 x这个位置,然后把[1, x - 1]清0即可。

查询第k小,可以二分然后判断。

复制代码
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define IOS ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
#define lson L, mid, cur << 1
#define rson mid + 1, R, cur << 1 | 1
const int maxn = 100000 + 20;
struct Node {
    int op, val;
}query[maxn];
vector<int>vc;
set<int>ss;
int sum[maxn << 2];
int add[maxn << 2];
void pushUp(int cur) {
    sum[cur] = sum[cur << 1] + sum[cur << 1 | 1];
}
void pushDown(int cur, int total) {
    if (add[cur] != -inf) {
        add[cur << 1] = add[cur];
        add[cur << 1 | 1] = add[cur];
        sum[cur << 1] = sum[cur << 1 | 1] = 0;
        add[cur] = -inf;
    }
}
void upDate(int be, int en, int val, int L, int R, int cur) {
    if (be > en) return;
    if (L >= be && R <= en) {
        add[cur] = val;
        sum[cur] = val;
        return;
    }
    pushDown(cur, R - L + 1);
    int mid = (L + R) >> 1;
    if (be <= mid) upDate(be, en, val, lson);
    if (en > mid) upDate(be, en, val, rson);
    pushUp(cur);
}
int ask(int be, int en, int L, int R, int cur) {
    if (en < be) return 0;
    if (L >= be && R <= en) return sum[cur];
    pushDown(cur, R - L + 1);
    int ans = 0, mid = (L + R) >> 1;
    if (be <= mid) ans += ask(be, en, lson);
    if (en > mid) ans += ask(be, en, rson);
    return ans;
}
#define root 1, n, 1
int n;
int slove(int x) { //要大于多少个number
    int be = 1, en = n;
    while (be <= en) {
        int mid = (be + en) >> 1;
        int res = ask(1, mid, root);
        if (res >= x) en = mid - 1;
        else be = mid + 1;
    }
    return vc[be];
}
void work() {
    int en = maxn << 2;
    for (int i = 0; i <= en - 1; ++i) add[i] = -inf;
    vc.push_back(-inf);
    int q;
    scanf("%d", &q);
    for (int i = 1; i <= q; ++i) {
        scanf("%d%d", &query[i].op, &query[i].val);
        ss.insert(query[i].val);
    }
    for (set<int> :: iterator it = ss.begin(); it != ss.end(); ++it) {
        vc.push_back(*it);
    }
    n = vc.size();
    n--;
    int nowHas = 0;
    for (int i = 1; i <= q; ++i) {
        int op = query[i].op, val = query[i].val;
        int pos = lower_bound(vc.begin(), vc.end(), val) - vc.begin();
        if (op == 1) {
            nowHas++;
            int has = ask(pos, pos, root);
            upDate(pos, pos, has + 1, root);
        } else if (op == 2) {
            int res = ask(1, pos, root);
            upDate(pos, pos, res, root);
            upDate(1, pos - 1, 0, root);
        } else if (op == 3) {
            int res = ask(1, n, root) - ask(1, pos, root);
            upDate(pos, pos, res, root);
            upDate(pos + 1, n, 0, root);
        } else if (op == 4) {
            printf("%d\n", slove(val));
        } else if (op == 5) {
            int res = ask(1, pos - 1, root);
            printf("%d\n", res);
        }
    }
//    printf("*****************\n");
//    printf("%d\n", ask(1, 3, root));
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code
复制代码

 

posted on   stupid_one  阅读(451)  评论(5编辑  收藏  举报

编辑推荐:
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
· 如何调用 DeepSeek 的自然语言处理 API 接口并集成到在线客服系统
< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

导航

统计

点击右上角即可分享
微信分享提示