HDU 6315 (线段树变形)

题意:
给出长度为n的b序列,b序列为1~n的一个排列,a序列初始为全0。
给出q次操作,add操作使a[l,r]+1,query操作求[l,r]的ai/bi的和。

思路:
对于一个ai/bi,只有当ai增加到bi时才有1个贡献,所以用线段树维护一个c数组,记录ai离下一次做出贡献还差多少次add。
当[l,r]中的min(c)==1时,把标记下推,当标记到达叶子节点是贡献+1。
因为b是1~n的排列,所以最多更新nlogn次,每次操作复杂度为logn,总体复杂度O(nlog^2n)

代码:

#include <iostream>
#include <iomanip>
#include <algorithm>
#include <cstring>
#include <cctype>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <map>
#include <list>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <sstream>
#define pb push_back
#define X first
#define Y second
#define ALL(x) x.begin(),x.end()
#define INS(x) inserter(x,x.begin())
#define pii pair<int,int>
#define qclear(a) while(!a.empty())a.pop();
#define lowbit(x) (x&-x)
#define sd(n) scanf("%d",&n)
#define sdd(n,m) scanf("%d%d",&n,&m)
#define sddd(n,m,k) scanf("%d%d%d",&n,&m,&k)
#define mst(a,b) memset(a,b,sizeof(a))
#define cout3(x,y,z) cout<<x<<" "<<y<<" "<<z<<endl
#define cout2(x,y) cout<<x<<" "<<y<<endl
#define cout1(x) cout<<x<<endl
#define IOS std::ios::sync_with_stdio(false)
#define SRAND srand((unsigned int)(time(0)))
typedef long long ll;
typedef unsigned long long ull;
typedef unsigned int uint;
using namespace std;
const double PI=acos(-1.0);
const int INF=0x3f3f3f3f;
const ll mod=1e9+7;
const double eps=1e-8;
const int maxn=100005;
const int maxm=10005;
struct node {
    int mn,div,ans,lazy;
};
node st[maxn<<2];
int b[maxn];
void pushdown(int o) {
    st[o<<1].lazy+=st[o].lazy;
    st[(o<<1)|1].lazy+=st[o].lazy;
    st[o<<1].mn-=st[o].lazy;
    st[(o<<1)|1].mn-=st[o].lazy;
    st[o].lazy=0;
}
void pushup(int o) {
    st[o].ans=st[o<<1].ans+st[(o<<1)|1].ans;
    st[o].mn=min(st[o<<1].mn,st[(o<<1)|1].mn);
}
void build(int o,int l,int r) {
    st[o].lazy=st[o].ans=0;
    if(l==r) {
        st[o].div=st[o].mn=b[l];
        st[o].ans=0;
        return ;
    }
    int mid=(l+r)>>1;
    build(o<<1,l,mid);
    build((o<<1)|1,mid+1,r);
    st[o].mn=min(st[o<<1].mn,st[(o<<1)|1].mn);
}
void update(int o,int l,int r,int ql,int qr) {
    if (l > r) return;
    if(l==ql&&r==qr&&st[o].mn>1) {
        st[o].lazy++;
        st[o].mn--;
        return ;
    }
    if(l==r&&st[o].mn==1) {
        st[o].mn=st[o].div;
        st[o].ans++;
        st[o].lazy=0;
        return ;
    }
    if(st[o].lazy>0)
        pushdown(o);
    int mid=(l+r)>>1;
    if(qr<=mid) {
        update(o<<1,l,mid,ql,qr);
    } else if(ql>mid) {
        update((o<<1)|1,mid+1,r,ql,qr);
    } else {
        update(o<<1,l,mid,ql,mid);
        update((o<<1)|1,mid+1,r,mid+1,qr);
    }
    pushup(o);
}
int query(int o,int l,int r,int ql,int qr) {
    if (l > r) return 0;
    if(ql<=l&&r<=qr) {
        return st[o].ans;
    }
    int mid=(l+r)>>1;
    if(qr<=mid) {
        return query(o<<1,l,mid,ql,qr);
    } else if(ql>mid) {
        return query((o<<1)|1,mid+1,r,ql,qr);
    } else {
        return query(o<<1,l,mid,ql,qr)+query((o<<1)|1,mid+1,r,ql,qr);
    }
}
void solve() {
    int n,q;
    while(~sdd(n,q)) {
        for(int i=1; i<=n; i++) {
            sd(b[i]);
        }
        build(1,1,n);
        while(q--) {
            char op[20];
            scanf("%s",op);
            int l,r;
            sdd(l,r);
            if(op[0]=='a') {
                update(1,1,n,l,r);
            } else {
                int ans=query(1,1,n,l,r);
                printf("%d\n",ans);
            }
        }
    }
    return ;
}
int main() {
#ifdef LOCAL
    freopen("in.txt","r",stdin);
//    freopen("out.txt","w",stdout);
#else
    //    freopen("","r",stdin);
    //    freopen("","w",stdout);
#endif
    solve();
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_38378637/article/details/81367923
今日推荐