2020-2021 ICPC Southwestern European Regional Contest (SWERC 2020) H - Figurines(可持久化线段树)

H - Figurines

题意:

有一个展览架,N个不同编号的模型,每天会往上放上模型或拿走模型。同时有一个算法, x i + 1 = ( x i + y i ) m o d N x_{i+1}=(x_{i}+y_i) mod N xi+1=(xi+yi)modN,其中 y i y_i yi d i d_i di天时,展览架中编号大于等于 x i x_i xi的个数。给出每天放上和拿走模型的情况,和每个 d i d_i di,求 x N x_N xN

解析:

由于N为1e5级别,无法直接开线段树或者set存每一天的状态,所以需要用可持久化线段树优化一下,基本属于模板题。

代码
#include <bits/stdc++.h>

using namespace std;
#define fast                          \
       ios_base::sync_with_stdio(false); \
       cin.tie(NULL);
const int N = 5e6 + 10;
const int M = 1e6 + 10;
const int INF = 0x3f3f3f3f;
const long long LINF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9 + 7;
const double eps = 1e-3;
#define lson (root << 1)
#define rson (root << 1 | 1)

int T[N], ls[N], rs[N], sum[N], idx;

void build(int &root, int l, int r) {
    root = ++idx;
    sum[root] = 0;
    if(l == r)  return;
    int mid = (l + r) >> 1;
    build(ls[root], l, mid);
    build(rs[root], mid + 1, r);
}
void update(int &root, int l, int r, int pre, int pos, int val) {
    root = ++idx;
    ls[root] = ls[pre], rs[root] = rs[pre];
    sum[root] = sum[pre] + val;
    if(l == r)  return;
    int mid = (l + r) >> 1;
    if(pos <= mid) update(ls[root], l, mid, ls[pre], pos, val);
    else            update(rs[root], mid + 1, r, rs[pre], pos, val);
}
int query(int root, int l, int r, int k) {
    if(k <= l)  return sum[root];
    if(l == r)  return sum[root];
    int mid = (l + r) >> 1;
    int res = 0;
    if(k <= mid)    res += query(ls[root], l, mid, k);
    res += query(rs[root], mid + 1, r, k);
    return res;
}
int n;
pair<int,int> solve(string s) {
    int c = s[0] == '+'?1:-1;
    int res = 0, len = s.size();
    for (int i = 1; i < len; i++) {
        res = res * 10 + s[i] - '0';
    }
    return {res, c};
}
int D[N];
int main(){
    ios::sync_with_stdio(false);
    string s;
    cin >> n;
    getline(cin, s);
    build(T[0], 0, n - 1);
    int cnt = 0;
    for (int i = 1; i <= n; i++) {
        getline(cin, s);
        stringstream ss;
        ss << s;
        while(ss >> s) {
            auto res = solve(s);
            cnt++;
            update(T[cnt], 0, n - 1, T[cnt - 1], res.first, res.second);
        }
        D[i] = cnt;
    }
    int x = 0;
    for (int i = 1; i <= n; i++) {
        int d;
        cin >> d;
        int res = query(T[D[d]], 0, n - 1, x);
        x = (x + res) % n;
    }
    cout << x << '\n';
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值