1. 程式人生 > >杭電多校第二場 1007 HDU-6315 Naive Operations(線段樹)

杭電多校第二場 1007 HDU-6315 Naive Operations(線段樹)

Naive Operations
Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 502768/502768 K (Java/Others)
Total Submission(s): 820    Accepted Submission(s): 302


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=l⌊ai/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.
1≤n,q≤100000, 1≤l≤r≤n, 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

題目大意:給出兩個陣列a和b,一開始陣列a中的所有元素都為0,陣列b為1-n的一個排列。接下來有q次詢問,詢問有以下兩種操作:

1、add l r   令a陣列區間[l,r]內的元素加一

2、query l r 查詢並輸出\sum_{i=l}^{r}\left \lfloor \frac{a_{i}}{b_{i}} \right \rfloor的值

題目思路:本題可以通過建立兩棵線段樹來解決。第一棵線段樹用來維護當前的ai還差多少達到bi的整數倍,這樣每次區間更新加一的時候,就將這個區間的值減一,當區間的最小值為0的時候,說明區間內就至少有一個結點達到了bi的倍數,就可以對最終的結果加1,另一棵線段樹就是用來維護最終答案,當一個區間在更新後最小值為0時,我們就用一個dfs找到為0的那個結點,再去更新第二棵線段樹,再將第一棵線段樹對應位置的值重新賦值為bi。查詢的時候藉助第二棵線段樹直接查詢即可。

由於b是1-n的排列,那麼\sum_{i=1}^{n}\left \lfloor n/b_{i} \right \rfloor就是O(nlogn)的,加上線段樹的操作,總體的複雜度就是O(nlog^2n)

具體實現看程式碼:

#include <bits/stdc++.h>
#define fi first
#define se second
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
#define lowbit(x) x&-x
#define MP make_pair
#define pb push_back
#define debug(x) cout<<x<<"= "<<x<<endl;
#define FIN freopen("in.txt","r",stdin);
using namespace std;
typedef long long ll;
typedef vector<int> vi;
typedef pair<int,int>pii;
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
const ll infll=0x3f3f3f3f3f3f3f3f;
const int MX=1e5+7;

int n,q;
int b[MX];
int MIN[MX<<2],sum[MX<<2],tag[MX<<2];
inline void push_up1(int rt){
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
inline void update1(int p,int l,int r,int rt){
    if(l==r){
        sum[rt]++;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m) update1(p,lson);
    else update1(p,rson);
    push_up1(rt);
}
inline int query(int L,int R,int l,int r,int rt){
    if(L<=l && r<=R) return sum[rt];
    int m=(l+r)>>1,res=0;
    if(L<=m) res+=query(L,R,lson);
    if(R>m) res+=query(L,R,rson);
    return res;
}

inline void push_up2(int rt){
    MIN[rt]=min(MIN[rt<<1],MIN[rt<<1|1]);
}
inline void push_down(int rt){
    if(tag[rt]){
        tag[rt<<1]+=tag[rt];tag[rt<<1|1]+=tag[rt];
        MIN[rt<<1]+=tag[rt];MIN[rt<<1|1]+=tag[rt];
        tag[rt]=0;
    }
}
inline void modity(int l,int r,int rt){
    if(l==r){
        update1(l,1,n,1);
        MIN[rt]=b[l];
        return;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if(!MIN[rt<<1]) modity(lson);
    if(!MIN[rt<<1|1]) modity(rson);
    push_up1(rt);
    push_up2(rt);
}
inline void update2(int L,int R,int l,int r,int rt){
    if(L<=l && r<=R){
        MIN[rt]--;
        tag[rt]--;
        if(!MIN[rt]) modity(l,r,rt);
        return;
    }
    push_down(rt);
    int m=(l+r)>>1;
    if(L<=m) update2(L,R,lson);
    if(R>m) update2(L,R,rson);
    push_up2(rt);
}

inline void build(int l,int r,int rt){
    sum[rt]=tag[rt]=0;
    if(l==r){
        MIN[rt]=b[l];
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up1(rt);
    push_up2(rt);
}

int main() {
    //FIN
    while(~scanf("%d%d",&n,&q)) {
        for(int i=1; i<=n; i++) scanf("%d",&b[i]);
        build(1,n,1);
        char op[10];
        int l,r;
        while(q--) {
            scanf("%s%d%d",op,&l,&r);
            if(op[0]=='a')
                update2(l,r,1,n,1);
            else {
                printf("%d\n",query(l,r,1,n,1));
            }
        }
    }
    return 0;
}