zoukankan      html  css  js  c++  java
  • 七夕——ORMAX(线段树)

    ORMAX

    题目链接:https://ac.nowcoder.com/acm/contest/18962/G

    题目描述:

    给定一个数组A,长度为n,你需要对该数组进行两种操作:

    查询操作:1 l r 存在子区间[X,Y] 使得AX or AX+1 or AX+2  ... AY-2 or AY-1 or AY的值最大,输出这个最大值。

    修改操作:2 l r x 将区间[l,r]的数全修改为x。

    这里or指或操作。

    见过最漂亮的线段树模板了,递归建树、递归维护

    这题确实可以用线段树做,因为一个数A或运算他自己的结果还是A(即A|A=A)所以区间修改操作时可以直接把所在的区间改成X,代码代码如下:

    #include<bits/stdc++.h>
    using namespace std;
    const int maxn = 1000001;
    int n, m, a[maxn], L[maxn << 2], R[maxn << 2], sum[maxn << 2], tag[maxn << 2], ans;
    void bulid(int x, int l, int r)
    {
        L[x] = l, R[x] = r;
        if(l == r)
        {
            sum[x] = a[l];
            return;
        }
        int mid = l + r >> 1;
        bulid(x << 1, l, mid);
        bulid(x << 1 | 1, mid + 1, r);
        sum[x] = sum[x << 1] | sum[x << 1 | 1];
    }
    void pushdown(int x, int data)
    {
        tag[x] = data;
        sum[x] = data;
    }
    void updata(int x, int l, int r, int data)
    {
        if(r < L[x] || l > R[x])
        {
            return;
        }
        if(l <= L[x] && r >= R[x])
        {
            sum[x] = data;
            tag[x] = data;
            return;
        }
        if(tag[x])
        {
            pushdown(x << 1, tag[x]);
            pushdown(x << 1 | 1, tag[x]);
            tag[x] = 0;
        }
        updata(x << 1, l, r, data);
        updata(x << 1 | 1, l, r, data);
        sum[x] = sum[x << 1] | sum[x << 1 | 1];
    }
    void getsum(int x, int l, int r)
    {
        if(r < L[x] || l > R[x])
        {
            return;
        }
        if(l <= L[x] && r >= R[x])
        {
            ans |= sum[x];
            return;
        }
        if(tag[x])
        {
            pushdown(x << 1, tag[x]);
            pushdown(x << 1 | 1, tag[x]);
            tag[x] = 0;
        }
        getsum(x << 1, l, r);
        getsum(x << 1 | 1, l, r);
    }
    int main()
    {
        scanf("%d%d", &n, &m);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d", &a[i]);
        }
        bulid(1, 1, n);
        for(int i = 1; i <= m; i++)
        {
            int op;
            scanf("%d", &op);
            if(op == 1)
            {
                int l, r;
                scanf("%d%d", &l, &r);
                ans = 0;
                getsum(1, l, r);
                printf("%d
    ", ans);
            }
            else
            {
                int l, r, k;
                scanf("%d%d%d", &l, &r, &k);
                updata(1, l, r, k);
            }
        }
        return 0;
    }

      放着欣赏。

  • 相关阅读:
    实际运用中DataSet、DataTable、DataRow点滴
    SQL语句AND 和 OR执行的优先级
    CS程序,服务器端弹出MessageBox.Show()之类的UI操作???禁止
    使用动态SQL语句实现简单的行列转置(动态产生列)
    表的行列转置
    统计每种车型的数量
    由CAST()函数在.NET1.1和.NET4.0下处理机制不同所引发的BUG
    转载——网站重构的8点建议
    float,double和decimal类型
    优化DB2缓冲页的大小
  • 原文地址:https://www.cnblogs.com/thx2199/p/15145757.html
Copyright © 2011-2022 走看看