zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    UIScrollView的滚屏
    ASIHTTPRequest 详解, 够详细
    Libxml2中使用xpath解析xml问题
    new Random()结果相同问题
    UINavigationController使用的一些技巧
    Objectivec 模拟http请求
    开发视频网站,asp.net视频文件转换.flv格式(转)
    jqueryjCarousel 配置选项
    NSDate和NSString之间的转换,(可以转时区的哈)
    NSLog的格式
  • 原文地址:https://www.cnblogs.com/kls123/p/9367101.html
Copyright © 2011-2022 走看看