bzoj2006: [NOI2010]超级钢琴(主席树+优先队列)

it2025-01-07  50

bzoj2006: [NOI2010]超级钢琴

bzoj2006: 超级钢琴

思路

对所有前缀和建权值线段树,先将所有右端点对应的最大的左端点丢进优先队列里,每次将优先队列队首的区间取出来后,将rk[r]++,从这个右端点对应的主席树区间中找到排名第rk[r]的值丢进优先队列,相当于用主席树求区间第k小。

代码

#include <bits/stdc++.h> using namespace std; #define dd(x) cout<<#x<<"="<<x<<" " #define rep(i,a,b) for(int i=(a);i<(b);i++) #define de(x) cout<<#x<<"="<<x<<"\n" #define mes(p) memset(p,0,sizeof(p)) #define fi first #define se second #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #define sz(x) (int)x.size() #define pb push_back #define ls (rt<<1) #define rs (ls|1) #define all(x) x.begin(),x.end() const int maxn=500005; typedef long long ll; typedef vector <int > vi; typedef pair <int, int> pi; int n,k,L,R, cnt; ll a[maxn], s[maxn]; int T[maxn], rk[maxn]; vector<ll > v; struct tr{ int sum,l,r; }t[maxn<<5]; struct node { ll s; int t; node (){} node(ll _s,int _t){ s=_s, t=_t; } bool operator < (const node& a) const{ return s<a.s; } }; priority_queue<node> q; void update(int pre,int &now,int l,int r,int pos){ now = ++ cnt; t[now].sum = t[pre].sum+1; if(l==r) return ; t[now].l=t[pre].l; t[now].r=t[pre].r; int mid = l+r>>1; if(pos<=mid) update(t[pre].l,t[now].l,l,mid,pos); else update(t[pre].r,t[now].r,mid+1,r,pos); } int qr(int x,int y,int l,int r,int k){ if(l==r) return l; int mid = l+r>>1; int sl = t[t[y].l].sum - t[t[x].l].sum; if(sl>=k) return qr(t[x].l,t[y].l,l,mid,k); else return qr(t[x].r,t[y].r,mid+1,r,k-sl); } int main(){ scanf("%d%d%d%d",&n,&k,&L,&R); rep(i,1,n+1) cin>>a[i], s[i]=s[i-1]+a[i],v.pb(s[i]); v.pb(0); sort(all(v)); v.erase(unique(all(v)),v.end()); int m= sz(v); update(T[0],T[1],1,m,lower_bound(all(v),0)-v.begin()+1); rep(i,2,n+2){ update(T[i-1],T[i],1,m,lower_bound(all(v),s[i-1])-v.begin()+1); int l=max(1,i-R), r=i-L; if(r<=0) continue; int ss = qr(T[l-1],T[r],1,m,1); q.push(node(s[i-1]-v[ss-1],i)); rk[i-1]=1; } ll ans = 0; while(k--){ ans += q.top().s; int x=q.top().t; q.pop(); int l=max(1,x-R), r=x-L, ss; ++rk[x-1]; if(rk[x-1]>t[T[r]].sum-t[T[l-1]].sum) continue; ss = qr(T[l-1],T[r],1,m,rk[x-1]); q.push(node(s[x-1]-v[ss-1],x)); } printf("%lld",ans); return 0; }

转载于:https://www.cnblogs.com/seast90/p/10836220.html

相关资源:数据结构—成绩单生成器
最新回复(0)