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;
    }
  • 相关阅读:
    SQL中 patindex函数的用法
    纵表与横表互转的SQL
    几种数据库的大数据批量插入【转】
    使用cmd命令行窗口操作SqlServer
    C#性能优化实践
    C# 图像处理(二)—— 黑白效果
    SQLSERVER系统视图
    SQLServer行列转换 Pivot UnPivot
    C#图片处理常见方法性能比较
    GSM局数据制作1(Erision)
  • 原文地址:https://www.cnblogs.com/kls123/p/9367101.html
Copyright © 2011-2022 走看看