zoukankan      html  css  js  c++  java
  • Q

    Q - Play With Sequence

     HDU - 3971 

    这个题目是一个线段树,比较特别的线段树,就是c询问一定次数之后重新排序建树来优化减低复杂度。

    第一次碰到这种题目有点迷。

    这个题目写还是很好写的,就是重新排序建树的位置不太好找。

    不过可以知道的是,这是更新花费时间和排序花费时间的一个平衡,这个是一个二次函数,这个二次函数的最低点可以自己测出来。

    现在可能有点听不懂,写完代码就很好理解了,

    我测的每隔2000次C的操作就重新建树排序是最优的。

    800,1000,2200,3000 都是可以的。

    #include <cstdio>
    #include <cstring>
    #include <cstdlib>
    #include <algorithm>
    #include <iostream>
    #include <queue>
    #include <string>
    #include <vector>
    #include <map>
    #define inf 0x3f3f3f3f
    #define inf64 0x3f3f3f3f3f3f3f3f
    using namespace std;
    const int maxn = 3e5 + 10;
    typedef long long ll;
    ll a[maxn], lc[maxn], rc[maxn], num[maxn];
    string s[maxn];
    struct node
    {
        ll lazy, max, min, len;
    }tree[maxn*16];
    void push_up(int id)
    {
        tree[id].max = max(tree[id << 1].max, tree[id << 1 | 1].max);
        tree[id].min = min(tree[id << 1].min, tree[id << 1 | 1].min);
        //printf("tree[%d].min=%lld tree[%d].max=%lld
    ", id, tree[id].min, id, tree[id].max);
    }
    
    void build(int id,int l,int r)
    {
        tree[id].len = r - l + 1;
        tree[id].lazy = 0;
        if(l==r)
        {
            tree[id].max = tree[id].min = a[l];
            return;
        }
        int mid = (l + r) >> 1;
        build(id << 1, l, mid);
        build(id << 1 | 1, mid + 1, r);
        push_up(id);
    }
    
    void push_down(int id)
    {
        if(tree[id].lazy)
        {
            int val = tree[id].lazy;
            tree[id << 1].max += val;
            tree[id << 1].min += val;
            tree[id << 1 | 1].max += val;
            tree[id << 1 | 1].min += val;
            tree[id << 1].lazy += val;
            tree[id << 1 | 1].lazy += val;
            // printf("tree[%d].max=%lld tree[%d].min=%lld
    ", id << 1, tree[id << 1].max, id << 1, tree[id << 1].min);
            // printf("tree[%d].max=%lld tree[%d].min=%lld
    ", id << 1 | 1, tree[id << 1 | 1].max, id << 1 | 1, tree[id << 1 | 1].min);
            tree[id].lazy = 0;
        }
    }
    void update(int id,int l,int r,ll x,ll y,ll val)
    {
        push_down(id);
        // printf("id=%d l=%d r=%d x=%lld y=%lld val=%lld
    ", id, l, r, x, y, val);
        if(tree[id].min>=x&&tree[id].max<=y)
        {
            tree[id].lazy = val;
            tree[id].min += val;
            tree[id].max += val;
            //printf("id=%d min=%lld max=%lld
    ", id, tree[id].min, tree[id].max);
            return;
        }
        int mid = (l + r) >> 1;
        if (tree[id << 1].max >= x && tree[id << 1].min <= y) update(id << 1, l, mid, x, y, val);
        if (tree[id << 1 | 1].max >= x && tree[id << 1 | 1].min <= y) update(id << 1 | 1, mid + 1, r, x, y, val);
        push_up(id);
    }
    
    int query(int id,int l,int r,ll x,ll y)
    {
        push_down(id);
        if(tree[id].max<=y&&tree[id].min>=x)
        {
            return tree[id].len;
        }
        int mid = (l + r) >> 1, ans = 0;
        if (tree[id << 1].max >= x && tree[id << 1].min <= y) ans += query(id << 1, l, mid, x, y);
        if (tree[id << 1 | 1].max >= x && tree[id << 1 | 1].min <= y) ans += query(id << 1 | 1, mid + 1, r, x, y);
        return ans;
    }
    
    void push_alldown(int id,int l,int r)
    {
        if(l==r)
        {
            a[l] = tree[id].max;
            return;
        }
        push_down(id);
        int mid = (l + r) >> 1;
        push_alldown(id << 1, l, mid);
        push_alldown(id << 1 | 1, mid + 1, r);
    }
    
    int main()
    {
        int n, m;
        while(scanf("%d%d",&n,&m)!=EOF)
        {
            for (int i = 1; i <= n; i++) scanf("%lld", &a[i]);
            sort(a + 1, a + 1 + n);
            build(1, 1, n);
            int cnt = 0;
            for(int i=1;i<=m;i++)
            {
                cin >> s[i];
                if (s[i] == "C") scanf("%lld%lld%lld", &lc[i], &rc[i], &num[i]), cnt++;
                else scanf("%lld%lld", &lc[i], &rc[i]), num[i] = 0;
            }
            int tot = 0;
            for(int i=1;i<=m;i++)
            {
                if(s[i]=="C")
                {
                    ++tot;
                    //push_alldown(1, 1, n);
                    //printf("lc[%d]=%lld rc[%d]=%lld num[%d]=%lld
    ", i, lc[i], i, rc[i], i, num[i]);
                    update(1, 1, n, lc[i], rc[i], num[i]);
                    if(tot%2100==0)
                    {
                        push_alldown(1, 1, n);
                        sort(a + 1, a + 1 + n);
                        build(1, 1, n);
                    }
                }
                else
                {
                    int ans = query(1, 1, n, lc[i], rc[i]);
                    printf("%d
    ", ans);
                }
            }
        }
    }
    线段树 排序建树
  • 相关阅读:
    oracle 创建数据库 创建表空间 创建用户
    Oracle 10G/11G 导入 导出
    winform与IE交互
    asihttprequest简单异步
    架构师的故事
    duobangotinySDP,rfc 2327
    duobangotinySAK,20121213
    doubango框架阅读计划
    并读<自己动手做操作系统>及<汇编语言2>
    SBJSON在xcode的应用中需要注意的
  • 原文地址:https://www.cnblogs.com/EchoZQN/p/11249393.html
Copyright © 2011-2022 走看看