IOI2014 Holiday

Holiday

健佳正在制定下个假期去台湾的游玩计划。在这个假期,健佳将会在城市之间奔波,并且参观这些城市的景点。

在台湾共有 \(n\) 个城市,它们全部位于一条高速公路上。这些城市连续地编号为 \(0\)\(n - 1\)。对于城市 \(i\) (\(0 < i < n - 1\)) 而言,与其相邻的城市是 \(i - 1\)\(i + 1\)。但是对于城市 \(0\),唯一与其相邻的是城市 \(1\)。而对于城市 \(n - 1\),唯一与其相邻的是城市 \(n - 2\)

每个城市都有若干景点。健佳有 \(d\) 天假期并且打算要参观尽量多的景点。健佳已经选择了假期开始要到访的第一个城市。在假期的每一天,健佳可以选择去一个相邻的城市,或者参观所在城市的所有景点,但是不能同时进行。即使健佳在同一个城市停留多次,他也不会去重复参观该城市的景点。请帮助健佳策划这个假期,以便能让他参观尽可能多的景点。

\(2 \leq n \leq 100000\)

题解

https://blog.csdn.net/CreationAugust/article/details/50821931

1

2

注意f,g计算的时候必须钦定一个能取到起点,一个不能取到起点。不然会算重。

CO int N=1e5+10;
int a[N];vector<int> b;
int root[N],tot;
int lc[N*18],rc[N*18],siz[N*18];
int64 sum[N*18];

#define mid ((l+r)>>1)
void insert(int&x,int l,int r,int p){
	++tot;
	lc[tot]=lc[x],rc[tot]=rc[x],siz[tot]=siz[x]+1;
	sum[tot]=sum[x]+b[p-1];
	x=tot;
	if(l==r) return;
	if(p<=mid) insert(lc[x],l,mid,p);
	else insert(rc[x],mid+1,r,p);
}
int64 query(int x,int y,int l,int r,int k){
	if(k<=0) return 0;
	if(l==r) return (int64)min(k,siz[x]-siz[y])*b[l-1];
	int s=siz[rc[x]]-siz[rc[y]];
	if(s>=k) return query(rc[x],rc[y],mid+1,r,k);
	else return sum[rc[x]]-sum[rc[y]]+query(lc[x],lc[y],l,mid,k-s);
}
#undef mid

int S;
int64 f[3*N],g[3*N],f1[3*N],g1[3*N];

void solve_f(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)>>1,pos=0;
	for(int i=L;i<=R;++i){
		int64 res=query(root[i],root[S-1],1,b.size(),mid-(i-S)); // count a[S]
		if(!pos or res>f[mid]) f[mid]=res,pos=i;
	}
	solve_f(l,mid-1,L,pos),solve_f(mid+1,r,pos,R);
}
void solve_g(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)>>1,pos=0;
	for(int i=R;i>=L;--i){
		int64 res=query(root[S-1],root[i-1],1,b.size(),mid-(S-i)); // doesn't count a[S]
		if(!pos or res>g[mid]) g[mid]=res,pos=i;
	}
	solve_g(l,mid-1,pos,R),solve_g(mid+1,r,L,pos);
}
void solve_f1(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)>>1,pos=0;
	for(int i=L;i<=R;++i){
		int64 res=query(root[i],root[S-1],1,b.size(),mid-2*(i-S));
		if(!pos or res>f1[mid]) f1[mid]=res,pos=i;
	}
	solve_f1(l,mid-1,L,pos),solve_f1(mid+1,r,pos,R);
}
void solve_g1(int l,int r,int L,int R){
	if(l>r) return;
	int mid=(l+r)>>1,pos=0;
	for(int i=R;i>=L;--i){
		int64 res=query(root[S-1],root[i-1],1,b.size(),mid-2*(S-i));
		if(!pos or res>g1[mid]) g1[mid]=res,pos=i;
	}
	solve_g1(l,mid-1,pos,R),solve_g1(mid+1,r,L,pos);
}

int main(){
	int n=read<int>();
	S=read<int>()+1;
	int m=read<int>();
	for(int i=1;i<=n;++i) b.push_back(read(a[i]));
	sort(b.begin(),b.end());
	b.erase(unique(b.begin(),b.end()),b.end());
	for(int i=1;i<=n;++i){
		a[i]=lower_bound(b.begin(),b.end(),a[i])-b.begin()+1;
		insert(root[i]=root[i-1],1,b.size(),a[i]);
	}
	solve_f(1,m,S,min(S+m,n));
	solve_g(1,m,max(S-m,1),S);
	solve_f1(1,m,S,min(S+m/2,n));
	solve_g1(1,m,max(S-m/2,1),S);
	int64 ans=0;
	for(int i=0;i<=m;++i) ans=max(ans,max(g1[i]+f[m-i],f1[i]+g[m-i]));
	printf("%lld\n",ans);
	return 0;
}

posted on 2020-02-13 10:19  autoint  阅读(162)  评论(0编辑  收藏  举报

导航