LOJ#6032. 「雅礼集训 2017 Day2」水箱 (主席树)

传送门

题解:
考虑最高木板,如果最终水位高于这个高度,那么全部都高于这个高度,枚举最终高度,用主席树快速查询贡献。
否则转化为子问题递归解决。

#include <bits/stdc++.h>
using namespace std;
typedef pair <int,int> pii;

const int RLEN=1<<18|1;
inline char nc() {
    static char ibuf[RLEN],*ib,*ob;
    (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin));
    return (ib==ob) ? -1 : *ib++;
}
inline int rd() {
    char ch=nc(); int i=0,f=1;
    while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();}
    while(isdigit(ch)) {i=(i<<1)+(i<<3)+ch-'0'; ch=nc();}
    return i*f;
}

const int N=3e5+50, L=32;
const int INF=0x3f3f3f3f;

int n,m;
namespace PST {
    int rt0[N],rt1[N],tot;
    struct node {
        int lc,rc,sze;
    } tr[N*(L+5)];
    inline int ask(int x,int y,int l,int r,int L,int R) {
        if(!y || !(tr[y].sze-tr[x].sze)) return 0;
        if(L<=l && r<=R) return tr[y].sze-tr[x].sze;
        int mid=(l+r)>>1;
        if(R<=mid) return ask(tr[x].lc,tr[y].lc,l,mid,L,R);
        else if(L>mid) return ask(tr[x].rc,tr[y].rc,mid+1,r,L,R);
        else return ask(tr[x].lc,tr[y].lc,l,mid,L,R)+ask(tr[x].rc,tr[y].rc,mid+1,r,L,R);
    }
    inline void inc(int x,int &y,int l,int r,int p) {
        y=++tot; tr[y]=tr[x]; ++tr[y].sze; if(l==r) return;
        int mid=(l+r)>>1; (p<=mid) ? inc(tr[x].lc,tr[y].lc,l,mid,p) : inc(tr[x].rc,tr[y].rc,mid+1,r,p);
    }
    inline void init(vector <pii> *lim) {
        for(int i=1;i<=n;i++) {
            rt0[i]=rt0[i-1];
            rt1[i]=rt1[i-1];
            for(auto j:lim[i]) {
                if(j.second) inc(rt1[i],rt1[i],0,INF,j.first);
                else inc(rt0[i],rt0[i],0,INF,j.first);
            }
        }       
    }
    inline int ask(int l,int r,int v,int rs=0) {
        rs+=ask(rt0[l-1],rt0[r],0,INF,v,INF+1);
        if(v) rs+=ask(rt1[l-1],rt1[r],0,INF,0,v-1);
        return rs;
    }
}

struct node {
    int l,r,h;
    node(int l=0,int r=0,int h=0) : l(l),r(r),h(h) {}
    friend inline bool operator <(const node &a,const node &b) {return a.h<b.h;}
} tr[N];
int li[N],pl[N],pr[N],ri[N],hi[N],ti[N],idx; pii st[N]; int tl;
map <int,int> id[N];
vector <int> edge[N];
vector <pii> lim[N];
vector <int> ht[N];
inline void clear() {
    for(int i=1;i<=n;i++) id[i].clear(), lim[i].clear();
    for(int i=1;i<=idx;i++) edge[i].clear(), ht[i].clear();
    for(int i=1;i<=n;i++) PST::rt0[i]=PST::rt1[i]=0;
    PST::tot=0;
}
inline int gl(int x) {return (li[x]==x) ? x : (li[x]=gl(li[x]));}
inline int gr(int x) {return (ri[x]==x) ? x : (ri[x]=gr(ri[x]));}
inline void merge(int x,int y) {ri[x]=y; li[y]=x;}
inline int findl(int l,int r,int v,int ans=0) {
    while(l<=r) {
        int mid=(l+r)>>1;
        if(st[mid].first<=v) r=mid-1;
        else ans=st[mid].second, l=mid+1;
    } return ans;
}

inline int dfs(int x) {
    int rs=0,s=0;
    for(auto j:ht[x]) {
        rs=max(rs,PST::ask(tr[x].l,tr[x].r,j));
        rs=max(rs,PST::ask(tr[x].l,tr[x].r,j+1));
    }
    rs=max(rs,PST::ask(tr[x].l,tr[x].r,tr[x].h));
    for(auto v:edge[x]) 
        s+=dfs(v);
    return max(rs,s);
}
int main() {
    for(int T=rd();T;T--) {
        clear(); n=rd(), m=rd();
        for(int i=1;i<n;i++) hi[i]=rd(),st[i]=pii(hi[i],i);
        sort(st+1,st+n);
        for(int i=1;i<=n;i++) li[i]=ri[i]=i, id[i][i]=ti[i]=++idx, tr[idx]=node(i,i,INF);

        for(int i=1,j;i<n;i=j+1) {
            j=i; while(j<n-1 && st[j+1].first==st[i].first) ++j;
            for(int k=i;k<=j;k++) pl[st[k].second]=gl(st[k].second), pr[st[k].second+1]=gr(st[k].second+1);
            for(int k=i;k<=j;k++) merge(st[k].second,st[k].second+1);
            for(int k=i;k<=j;k++) {
                if(gl(st[k].second)==pl[st[k].second]) {
                    int l=gl(st[k].second), r=gr(st[k].second);
                    id[l][r]=++idx; tr[idx]=node(l,r,INF);
                } 
                edge[idx].push_back(ti[pl[st[k].second]]);
                tr[ti[pl[st[k].second]]].h=st[k].first-1;
                if(gr(st[k].second+1)==pr[st[k].second+1]) {
                    edge[idx].push_back(ti[st[k].second+1]);
                    tr[ti[st[k].second+1]].h=st[k].first-1; 
                }
            }
            for(int k=i;k<=j;k++) ti[gl(st[k].second)]=id[gl(st[k].second)][gr(st[k].second)];
        }

        for(int i=1;i<=m;i++) {
            int pos=rd(), yc=rd(), ki=rd();
            lim[pos].push_back(pii(yc,ki));
        } PST::init(lim);

        st[tl=1]=pii(INF,1);
        for(int i=1;i<=n;i++) {
            for(auto &j:lim[i]) {
                int l=findl(1,tl,j.first);
                j.second=l;
            }
            while(tl && st[tl].first<hi[i]) --tl;
            st[++tl]=pii(hi[i],i+1);
        }
        st[tl=1]=pii(INF,n);
        for(int i=n;i>=1;i--) {
            for(auto j:lim[i]) {
                int r=findl(1,tl,j.first);
                ht[id[j.second][r]].push_back(j.first);
            }
            while(tl && st[tl].first<hi[i-1]) --tl;
            st[++tl]=pii(hi[i-1],i-1);
        }

        cout<<dfs(idx)<<'\n';
    }
} 

猜你喜欢

转载自blog.csdn.net/qq_35649707/article/details/80515543
今日推荐