• hdu 6315 Naive Operations (2018 Multi-University Training Contest 2 1007)


    Naive Operations

    Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
    Total Submission(s): 0    Accepted Submission(s): 0


    Problem Description
    In a galaxy far, far away, there are two integer sequence a and b of length n.
    b is a static permutation of 1 to n. Initially a is filled with zeroes.
    There are two kind of operations:
    1. add l r: add one for al,al+1...ar
    2. query l r: query ri=lai/bi
     
    Input
    There are multiple test cases, please read till the end of input file.
    For each test case, in the first line, two integers n,q, representing the length of a,b and the number of queries.
    In the second line, n integers separated by spaces, representing permutation b.
    In the following q lines, each line is either in the form 'add l r' or 'query l r', representing an operation.
    1n,q1000001lrn, there're no more than 5 test cases.
     
    Output
    Output the answer for each 'query', each one line.
     
    Sample Input
    5 12 1 5 2 4 3
    add 1 4
    query 1 4
    add 2 5
    query 2 5
    add 3 5
    query 1 5
    add 2 4
    query 1 4
    add 2 5
    query 2 5
    add 2 2
    query 1 5
     
    Sample Output
    1 1 2 4 4 6
     
    思路:
    很明显的线段树,难点在于如何处理ai/bi的向下取整,我们可以对bi建一棵线段树,那么每次add(l,r)操作我们就可以抽象成(l,r)减一,如果区间【l,r】中有数字变为0,则表示b[i]这个数+1,再建一棵线段树储存每个区间+1的信息并将这个数变为原先的值继续循环就好了,querry(l,r),就直接在第二棵线段树上求区间值的和就可以了。
     
    之前想到这个思路一直不敢写,感觉会超时,后面问了一下学长,复杂度没问题就AC了 。
    实现代码:
     
    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    #define mid int m = (l + r) >> 1
    const int inf = 0x3f3f3f3f;
    const int M = 1e5+10;
    double lazy[M<<2];
    double b[M],num[M],sum[M<<2],minn[M<<2];
    vector<int>v;
    void pushup(int rt){
        minn[rt] = min(minn[rt<<1],minn[rt<<1|1]);
    }
    
    void pushdown(int rt){
         if(lazy[rt]){
            lazy[rt<<1] += lazy[rt];
            lazy[rt<<1|1] += lazy[rt];
            minn[rt<<1] -= lazy[rt];
            minn[rt<<1|1] -= lazy[rt];
            lazy[rt] = 0;
         }
    }
    
    void build(int l,int r,int rt){
        lazy[rt] = 0; minn[rt] = inf;
        if(l == r){
            minn[rt] = b[l];
            return ;
        }
        mid;
        build(lson);
        build(rson);
        pushup(rt);
    }
    
    void update(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            minn[rt] -= 1;
            lazy[rt] += 1;
            return ;
        }
        pushdown(rt);
        mid;
        if(L <= m) update(L,R,lson);
        if(R > m) update(L,R,rson);
        pushup(rt);
    }
    
    void update2(int p,int l,int r,int rt){
        if(l == r){
            minn[rt] = b[l];
            return ;
        }
        mid;
        pushdown(rt);
        if(p <= m) update2(p,lson);
        else update2(p,rson);
        pushup(rt);
    }
    
    int Query(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            return minn[rt];
        }
        mid;
        pushdown(rt);
        int ret = inf;
        if(L <= m) ret = min(Query(L,R,lson),ret);
        if(R > m) ret = min(Query(L,R,rson),ret);
        return ret;
    }
    
    void query1(int l,int r,int rt){
        if(l == r){
            v.push_back(l);
            return ;
        }
        mid;
        pushdown(rt);
        pushdown(rt);
        if(minn[rt<<1] == 0) query1(lson);
        if(minn[rt<<1|1] == 0) query1(rson);
    }
    
    void pushup1(int rt){
        sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    }
    
    void build1(int l,int r,int rt){
        sum[rt] = 0;
        if(l == r){
            sum[rt] =  0;
            return ;
        }
        mid;
        build1(lson);
        build1(rson);
        pushup1(rt);
    }
    
    void update1(int p,int l,int r,int rt){
        if(l == r){
            sum[rt] += 1;
            return ;
        }
        mid;
        if(p <= m) update1(p,lson);
        else update1(p,rson);
        pushup1(rt);
    }
    
    int query(int L,int R,int l,int r,int rt){
        if(L <= l&&R >= r){
            return sum[rt];
        }
        mid;
        int ret = 0;
        if(L <= m) ret += query(L,R,lson);
        if(R > m) ret += query(L,R,rson);
        return ret;
    }
    
    int main()
    {
        int n,q,x,l,r;
        char op[100];
        while(scanf("%d%d",&n,&q)!=EOF){
            for(int i = 1;i <= n;i ++){
                scanf("%d",&x);
                b[i] = x;
            }
            build(1,n,1);
            build1(1,n,1);
            while(q--){
                scanf("%s",op);
                if(op[0] == 'a'){
                    //cout<<"update"<<endl;
                    scanf("%d%d",&l,&r);
                    update(l,r,1,n,1); //将第一棵树的l,r区间-1
                    int cnt = Query(l,r,1,n,1);//求第一棵树的l,r区间的最小值
                    //cout<<"cnt: "<<cnt<<endl;
                    if(cnt == 0){  //如果区间最小值为0
                        query1(1,n,1);  //找到区间所有0的下表寸进vector里
                        for(int i = 0;i < v.size(); i++){ //遍历
                            //cout<<"v[i] :"<<v[i]<<endl;
                            update1(v[i],1,n,1); //在第二颗数记下更新值
                            update2(v[i],1,n,1); //将现在为0的数变成原来的值
                        }
                        v.clear();
                    }
                }
                else {
                    //cout<<"query"<<endl;
                     scanf("%d%d",&l,&r);
                     int ans = query(l,r,1,n,1);
                     printf("%d
    ",ans);
                }
            }
        } 
        return 0;
    }
  • 相关阅读:
    【bzoj2190】: [SDOI2008]仪仗队 数论-欧拉函数
    【bzoj2751】[HAOI2012]容易题(easy) 数论-快速幂
    【bzoj2186】: [Sdoi2008]沙拉公主的困惑 数论-欧拉函数
    这里会有你想要的,已收录css , js相关文章
    Vue源码解析--实现一个指令解析器 Compile
    九宫格抽奖
    12行代码简单实现跑马灯文字匀速滚动
    滑弯曲弧形效果的插件-arctext.js改造
    几种拼图小游戏封装
    倒计时
  • 原文地址:https://www.cnblogs.com/kls123/p/9367101.html
Copyright © 2020-2023  润新知