记录编号 390891 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2011]拆迁队 最终得分 100
用户昵称 Gravatar_Itachi 是否通过 通过
代码语言 C++ 运行时间 0.958 s
提交时间 2017-04-04 15:56:10 内存使用 14.79 MiB
显示代码纯文本
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
char cc;inline void R_int(int &x){
	while(cc=getchar(),cc<'!');x=cc-48;
	while(cc=getchar(),cc>'!')x=x*10+cc-48;
}
#define LL long long
const int maxn=100005<<1,INF=0x3f3f3f3f;
struct Rabit_tree {int to,next;}e[maxn];
int n,st[maxn],cot,g[maxn],num[maxn],head[maxn],len=1,c[maxn],X[maxn];
LL A[maxn],B[maxn],f[maxn],Y[maxn];
void Set(int prt,int son){
	e[++len].to=son,e[len].next=head[prt],head[prt]=len;
}
void Add(register int i,int x){
	for(;i;i-=i&(-i))c[i]=max(c[i],x);
}
int Get(register int i){
	int res=-INF;for(;i<=cot;i+=i&(-i))res=max(res,c[i]);return res;
}
#define to e[i].to
void Rabit_in(){
	R_int(n);int i,rt,x;
	for(i=1;i<=n;i++)R_int(x),A[i]=x,st[i]=i-A[i];
	for(i=1;i<=n;i++)R_int(x),B[i]=x;
	st[cot=n+1]=0,sort(st+1,st+cot+1),cot=unique(st+1,st+cot+1)-st-1;
	for(i=0;i<=n;i++)num[i]=lower_bound(st+1,st+cot+1,i-A[i])-st;
	for(i=1;i<=cot;i++)c[i]=-INF;
	Set(g[0]=0,0),Add(num[0],g[0]);
	for(rt=1;rt<=n;rt++){
		g[rt]=Get(num[rt])+1;
		if(g[rt]>0)Set(g[rt],rt),Add(num[rt],g[rt]);			
	}
}
int q[maxn],Dep,tmp[maxn],Q[maxn],s,t;
bool Cmp(int a,int b){
	if(num[a]==num[b])return g[a]<g[b];
	return num[a]>num[b];
}
double Get(int a,int b){return (Y[a]-Y[b])/(double)(X[a]-X[b]);}
LL Run(int x,int y){
	return f[y]+(x-y)*1ll*(x-y-1)/2ll+A[y]*1ll*(x-y-1);
}
bool Check(int a,int b,int c){
	if(num[a]==num[b])return Y[a]>=Y[b];
	return Get(c,a)>=Get(b,a);
}
void Dig(int x){
	if(s>t)return;
	int l=s,r=t-1,mid;double k=x;
	while(l<=r){
		mid=(l+r)>>1;
		if(Get(q[mid+1],q[mid])>=k)l=mid+1;else r=mid-1;
	}
	f[x]=min(f[x],Run(x,q[l]));
}
void Rabit_run(int l,int r){
	if(l==r){if(g[Q[l]]==Dep)f[Q[l]]+=B[Q[l]]+A[Q[l]];return;}
	int mid=(l+r)>>1,cnt=0,i;s=1,t=0;	
	for(i=l;i<=mid;i++)if(g[Q[i]]<Dep)tmp[cnt++]=Q[i];
	for(i=mid+1;i<=r;i++)if(g[Q[i]]==Dep)tmp[cnt++]=Q[i];
	sort(tmp,tmp+cnt,Cmp);
	for(i=0;i<cnt;i++)
		if(g[tmp[i]]<Dep){
			while(s<t&&Check(q[t-1],q[t],tmp[i]))t--;
			q[++t]=tmp[i];
		}
		else Dig(tmp[i]);
	Rabit_run(l,mid);Rabit_run(mid+1,r);
}
void Rabit_ans(){
	int res=Get(1),rt,i,cnt;LL ans=1ll<<50;
	for(rt=1;rt<=res;rt++){
		cnt=0;Dep=rt;
		for(i=head[rt-1];i;i=e[i].next)
			Q[++cnt]=to,X[to]=A[to]-to,
			Y[to]=-(f[to]+to*1ll*(to+1ll)/2ll-A[to]*(to+1ll));
		for(i=head[rt];i;i=e[i].next)Q[++cnt]=to,f[to]=ans;
		sort(Q+1,Q+cnt+1);Rabit_run(1,cnt);
	}
	for(i=head[res];i;i=e[i].next)
		ans=min(ans,f[to]+A[to]*1ll*(n-to)+(n-to+1)*1ll*(n-to)/2ll);
	printf("%d %lld\n",res,ans);
}
int main(){
	freopen("lanxisi.in","r",stdin);freopen("lanxisi.out","w",stdout);
	Rabit_in();Rabit_ans();
	fclose(stdin);fclose(stdout);return 0;
}