zoukankan      html  css  js  c++  java
  • [ICPC2020南京J] Just Another Game of Stones

    [ICPC2020南京J] Just Another Game of Stones - 线段树

    Description

    给定一串石子堆 (b_{i}),有如下两种操作:

    将区间 ([l,r]) 中的石子堆中的石子数量变为 (max(b_{i}, x))

    取出区间 ([l,r]) 中的石子堆,新增第 (r-l+2) 个石子堆,其中石子数量为 (x)。询问有多少种方法拿石子使得转变为必胜态。

    Solution

    对这个 Nim 游戏的条件稍作变形,能转化为求区间内多少个数指定位是 1

    Segment tree beats, 区间最值操作需要维护:区间最小值、区间次小值、区间最小值个数

    对于修改值夹在最小和次小之间的情况直接刷掉最小值,而同时大于等于最小和次小的则递归处理

    #include <bits/stdc++.h>
    using namespace std;
    
    #define int long long
    
    int n, q;
    
    unsigned hight_bit(unsigned x)
    {                        //0010 1100 0000 0000 0000 0000 0000 0000 0000 0001
        x = x | (x >> 1);    //0011 1110 0000 0000 0000 0000 0000 0000 0000 0000
        x = x | (x >> 2);    //0011 1111 1000 0000 0000 0000 0000 0000 0000 0000
        x = x | (x >> 4);    //0011 1111 1111 1000 0000 0000 0000 0000 0000 0000
        x = x | (x >> 8);    //0011 1111 1111 1111 1111 1000 0000 0000 0000 0000
        x = x | (x >> 16);   //0011 1111 1111 1111 1111 1111 1111 1111 1111 1111
        return (x + 1) >> 1; //0100 0000 0000 0000 0000 0000 0000 0000 0000 0000
    }
    
    int ffs(int x)
    {
        return __builtin_ffs(hight_bit(x));
    }
    
    struct Node
    {
        int min_value, submin_value, min_count, sum[30];
        Node()
        {
            min_value = 1e18;
            submin_value = 1e18;
            min_count = 0;
            for (int i = 0; i < 30; i++)
                sum[i] = 0;
        }
        Node operator+(const Node &rhs)
        {
            Node res;
            for (int i = 0; i < 30; i++)
                res.sum[i] = sum[i] + rhs.sum[i];
            res.min_value = min(min_value, rhs.min_value);
            res.submin_value = min(submin_value, rhs.submin_value);
            res.min_count = 0;
            if (min_value != rhs.min_value)
                res.submin_value = min(res.submin_value, max(min_value, rhs.min_value));
            if (res.min_value == min_value)
                res.min_count += min_count;
            if (res.min_value == rhs.min_value)
                res.min_count += rhs.min_count;
            return res;
        }
        void Set(int x)
        {
            min_value = x;
            submin_value = 1e18;
            min_count = 1;
            for (int i = 0; i < 30; i++)
                if (x & (1 << i))
                    sum[i] = 1;
                else
                    sum[i] = 0;
        }
        int xor_sum()
        {
            int ans = 0;
            for (int i = 0; i < 30; i++)
                if (sum[i] & 1)
                    ans += 1 << i;
            return ans;
        }
        int getans()
        {
            int hb = ffs(xor_sum());
            return hb ? sum[hb - 1] : 0;
        }
    } nodes[1000005];
    
    void pushup(int p)
    {
        nodes[p] = nodes[p * 2] + nodes[p * 2 + 1];
    }
    
    void put(int p, int x)
    {
        if (x <= nodes[p].min_value)
            return;
        int tmp = nodes[p].min_value;
        for (int i = 0; i < 30; i++)
            if (tmp & (1 << i))
                nodes[p].sum[i] -= nodes[p].min_count;
        nodes[p].min_value = tmp = x;
        for (int i = 0; i < 30; i++)
            if (tmp & (1 << i))
                nodes[p].sum[i] += nodes[p].min_count;
    }
    
    void pushdown(int p)
    {
        put(p * 2, nodes[p].min_value);
        put(p * 2 + 1, nodes[p].min_value);
    }
    
    void build(int p, int l, int r, const vector<int> &src)
    {
        if (l == r)
        {
            nodes[p].Set(src[l]);
        }
        else
        {
            build(p * 2, l, (l + r) / 2, src);
            build(p * 2 + 1, (l + r) / 2 + 1, r, src);
            pushup(p);
        }
    }
    
    void modify(int p, int l, int r, int ql, int qr, int x)
    {
        if (l > qr || r < ql || x <= nodes[p].min_value)
            return;
        if (l >= ql && r <= qr && x <= nodes[p].submin_value)
            put(p, x);
        else
        {
            pushdown(p);
            modify(p * 2, l, (l + r) / 2, ql, qr, x);
            modify(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr, x);
            pushup(p);
        }
    }
    
    Node query(int p, int l, int r, int ql, int qr)
    {
        if (l > qr || r < ql)
            return Node();
        if (l >= ql && r <= qr)
            return nodes[p];
        pushdown(p);
        return query(p * 2, l, (l + r) / 2, ql, qr) + query(p * 2 + 1, (l + r) / 2 + 1, r, ql, qr);
    }
    
    signed main()
    {
        ios::sync_with_stdio(false);
        cin >> n >> q;
        vector<int> a(n + 2);
        for (int i = 1; i <= n; i++)
            cin >> a[i];
        build(1, 1, n, a);
        for (int i = 1; i <= q; i++)
        {
            int op, l, r, x;
            cin >> op >> l >> r >> x;
            if (op == 1)
            {
                modify(1, 1, n, l, r, x);
            }
            else
            {
                Node node;
                node.Set(x);
                auto tmp = query(1, 1, n, l, r);
                auto res = query(1, 1, n, l, r) + node;
                cout << (query(1, 1, n, l, r) + node).getans() << endl;
            }
        }
    }
    
  • 相关阅读:
    Jmeter-分布式
    Jmeter 重要测试指标释义
    Jmeter-12-如何使用Plugin Manager
    Jmeter-Java heap内存溢出
    Centos 6 FTP 配置
    Jmeter-8-FTP测试
    数据库介绍与分类
    WCP源码分析 与SpringMVC学习资料
    mvc 各种返回值
    JavaWeb工程 目录结构
  • 原文地址:https://www.cnblogs.com/mollnn/p/14587025.html
Copyright © 2011-2022 走看看