zoukankan      html  css  js  c++  java
  • noip模拟赛 无题

    分析:这道题和以前做过的模拟赛题很像:传送门.

          对于前30%的数据可以直接暴力求,k=1的数据利用线段树求区间最大值,没有修改操作可以用主席树.100%的数据主席树是肯定用不了的,观察到K非常小,可以用线段树来暴力维护.

          线段树记录每个区间内的第k小值(1≤k≤10),其它的操作没啥变化,就是pushup的时候要把两棵子树的信息给合并起来,用两个指针就好了.

          要维护的信息特别少,并且可以用线段树来维护的可以考虑用线段树来暴力维护.

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    
    using namespace std;
    
    const int maxn = 100010;
    
    struct node
    {
        int minn[20];
    }e[maxn << 2];
    
    int n, m, tag[maxn << 2];
    
    node hebing(node a, node b)
    {
        int p1 = 1, p2 = 1;
        node temp;
        for (int i = 1; i <= 10; i++)
        {
            if (a.minn[p1] > b.minn[p2])
                temp.minn[i] = a.minn[p1++];
            else
                temp.minn[i] = b.minn[p2++];
        }
        return temp;
    }
    
    void pushup(int o)
    {
        e[o] = hebing(e[o * 2], e[o * 2 + 1]);
    }
    
    void color(int o, int v)
    {
        tag[o] += v;
        for (int i = 1; i <= 10; i++)
            if (e[o].minn[i])
            e[o].minn[i] += v;
    }
    
    void pushdown(int o)
    {
        if (tag[o])
        {
            color(o * 2, tag[o]);
            color(o * 2 + 1, tag[o]);
            tag[o] = 0;
        }
    }
    
    void build(int o, int l, int r)
    {
        if (l == r)
        {
            scanf("%d", &e[o].minn[1]);
            return;
        }
        int mid = (l + r) >> 1;
        build(o * 2, l, mid);
        build(o * 2 + 1, mid + 1, r);
        pushup(o); 
    }
    
    void update(int o, int l, int r, int x, int y, int v)
    {
        if (x <= l && r <= y)
        {
            color(o, v);
            return;
        }
        pushdown(o);
        int mid = (l + r) >> 1;
        if (x <= mid)
            update(o * 2, l, mid, x, y, v);
        if (y > mid)
            update(o * 2 + 1, mid + 1, r, x, y, v);
        pushup(o);
    }
    
    node query(int o, int l, int r, int x, int y)
    {
        if (x <= l && r <= y)
            return e[o];
        pushdown(o);    
        int mid = (l + r) >> 1;
        node temp;
        bool flag = false;
        if (x <= mid)
        {
            if (!flag)
                temp = query(o * 2, l, mid, x, y);
            else
                temp = hebing(temp, query(o * 2, l, mid, x, y));
            flag = 1;
        }
        if (y > mid)
        {
            if (!flag)
                temp = query(o * 2 + 1, mid + 1, r, x, y);
            else
                temp = hebing(temp, query(o * 2 + 1, mid + 1, r, x, y));
        }
        return temp;
    }
    
    int main()
    {
        scanf("%d%d", &n, &m);
        build(1, 1, n);
        for (int i = 1; i <= m; i++)
        {
            int op, l, r, k;
            scanf("%d%d%d%d", &op, &l, &r, &k);
            if (op == 0)
            {
                if (r - l + 1 < k)
                    printf("-1
    ");
                else
                    printf("%d
    ", query(1, 1, n, l, r).minn[k]);
            }
            else
                update(1, 1, n, l, r, k);
        }
    
        return 0;
    }
  • 相关阅读:
    成员对象和封闭类
    静态成员
    this指针
    类型构造构造函数
    拷贝构造函数
    C++
    矩阵快速幂求递推式
    对浅拷贝和深拷贝的基本理解
    传引用作为形参和返回值_节省参数拷贝的时间
    namespace的基本知识
  • 原文地址:https://www.cnblogs.com/zbtrs/p/7765999.html
Copyright © 2011-2022 走看看