[决策单调性 分治 主席树] BZOJ 4367 [IOI2014]holiday假期

来源:互联网 发布:linux socket编程 pdf 编辑:程序博客网 时间:2024/05/14 13:20

比较显然的做法 枚举l,r 然后主席树

这题有很多单调性

可以利用

对一个确定的l 最优的r 是单调的 来分治


#include<cstdio>#include<cstdlib>#include<algorithm>using namespace std;typedef long long ll;inline char nc(){static char buf[100000],*p1=buf,*p2=buf;if (p1==p2) { p2=(p1=buf)+fread(buf,1,100000,stdin); if (p1==p2) return EOF; }return *p1++;}inline void read(int &x){char c=nc(),b=1;for (;!(c>='0' && c<='9');c=nc()) if (c=='-') b=-1;for (x=0;c>='0' && c<='9';x=x*10+c-'0',c=nc()); x*=b;}const int N=100005;int root[N],ls[18*N],rs[18*N],cnt[18*N];ll sum[18*N];int ncnt;int sx[N],icnt;inline int Bin(int x){return lower_bound(sx+1,sx+icnt+1,x)-sx;}inline void update(int x){cnt[x]=cnt[ls[x]]+cnt[rs[x]];sum[x]=sum[ls[x]]+sum[rs[x]];}void Modify(int &y,int x,int l,int r,int t,int f){y=++ncnt; int mid=(l+r)>>1;if (l==r){cnt[y]=cnt[x]+f;sum[y]=sum[x]+f*sx[t];return;}if (t<=mid)rs[y]=rs[x],Modify(ls[y],ls[x],l,mid,t,f),update(y);elsels[y]=ls[x],Modify(rs[y],rs[x],mid+1,r,t,f),update(y);}inline ll Query(int y,int x,int k,int l,int r){if (l==r)return (ll)min(k,cnt[y])*sx[l];int tmp=cnt[rs[y]]-cnt[rs[x]],mid=(l+r)>>1;if (k<=tmp)return Query(rs[y],rs[x],k,mid+1,r);elsereturn sum[rs[y]]-sum[rs[x]]+Query(ls[y],ls[x],k-tmp,l,mid);}int n,st,d;int a[N];ll ans;void Solve(int l,int r,int s,int t){int mid=(s+t)>>1,mi=r,rest;ll best=0,tmp;for (int i=l;i<=r;i++){rest=(mid-i)+min(mid-st,st-i);rest=d-rest;if (rest>0){tmp=Query(root[mid],root[i-1],rest,1,icnt);if (tmp>best) best=tmp,mi=i;}}ans=max(ans,best);if (s<=mid-1) Solve(l,mi,s,mid-1);if (mid+1<=t) Solve(mi,r,mid+1,t);}int main(){ll tem;freopen("holiday.in","r",stdin);freopen("holiday.out","w",stdout);read(n); read(st); read(d); st++;for (int i=1;i<=n;i++)read(a[i]),sx[++icnt]=a[i];sort(sx+1,sx+icnt+1); icnt=unique(sx+1,sx+icnt+1)-sx-1;for (int i=1;i<=n;i++) a[i]=Bin(a[i]);for (int i=1;i<=n;i++)Modify(root[i],root[i-1],1,icnt,a[i],1);Solve(1,st,st,n);printf("%lld\n",ans);return 0;}


0 0
原创粉丝点击