记录编号 587149 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 [国家集训队2011]拆迁队 最终得分 100
用户昵称 Gravatar┭┮﹏┭┮ 是否通过 通过
代码语言 C++ 运行时间 0.930 s
提交时间 2024-03-15 18:53:31 内存使用 12.60 MiB
显示代码纯文本
#include <bits/stdc++.h>
using namespace std;
#define ll long long
const int N = 1e5+10;
const ll inf = 1e17;
int n,cnt;
ll A[N],B[N],a[N],b[N],c[N];
ll f[N],g[N],ans,s = inf;
struct made{
    ll a,g;int id;
    int f,f2;
    bool operator < (const made x)const{
        return g < x.g;
    }
}w[N],s1[N],s2[N];
bool cmp1(made x,made y){
    return x.id < y.id;
}
bool cmp2(made x,made y){
    return x.a < y.a;
}


struct BIT{
    int c[N];
    inline int lowbit(int x){return x & (-x);}
    void clear(){memset(c,0,sizeof c);}
    void add(int x,int val){for(;x <= n+1;x += lowbit(x))c[x] = max(c[x],val);}
    int ask(int x){
        int ans = 0;
        for(;x > 0;x -= lowbit(x))ans = max(ans,c[x]+1);
        return ans;
    }
}t;


ll X(int x){return 2 * (A[x] - x);}
ll Y(int x){return (2*A[x] - x) * (x + 1) - 2 * f[x];}
int q[N],L,R;
void add(int x){
    int i = s2[x].id;
    while(L < R && (Y(q[R]) - Y(q[R-1])) * (X(i) - X(q[R])) <= (X(q[R]) - X(q[R-1])) * (Y(i) - Y(q[R])))R--;//Y打成X 调了4h 
    q[++R] = i;
}
int find(int x,int l,int r){
    while(l < r){
        int mid = l + r >> 1;
        if((Y(q[mid+1]) - Y(q[mid])) > x * (X(q[mid+1]) - X(q[mid])))l = mid+1;
        else r = mid;
    }
    return q[l];
}//二分 
void ask(int x){
    if(L <= R){
        int i = s2[x].id,j = find(s2[x].id,L,R);
        f[i] = min(f[i],f[j] + (2*A[j]+i-j)*(i-j-1)/2+b[i]);
    }
}
void CDQ(int l,int r){
    if(l == r)return;
    int mid = l + r >> 1;
    CDQ(l,mid);
    //
    L = 1,R = 0;
    for(int i = l;i <= r;i++){
        s1[i].f2 = (i > mid);
        s2[i] = s1[i];
    }
    sort(s2+l,s2+r+1,cmp2);
    for(int i = l;i <= r;i++){
        if(!s2[i].f && !s2[i].f2)add(i);
        if(s2[i].f && s2[i].f2)ask(i);
    }
    CDQ(mid+1,r);
}
int main(){
	freopen("lanxisi.in","r",stdin);
    freopen("lanxisi.out","w",stdout);
    scanf("%d",&n);
    for(int i = 1;i <= n;i++)scanf("%lld",&A[i]),a[i] = A[i] - i,c[i] = a[i];
    for(int i = 1;i <= n;i++)scanf("%lld",&B[i]),b[i] = A[i] + B[i];
    sort(c+1,c+2+n);
    int m = unique(c+1,c+2+n) - (c+2);
    for(int i = 1;i <= n;i++){
        if(a[i] < 0){g[i]= -1;continue;}
        int x = lower_bound(c+1,c+1+m,a[i])-c;
        g[i] = t.ask(x);
        t.add(x,g[i]);
        ans = max(g[i],ans);
    }
    w[n+1] = {0,0,0,0,0};//额外的0号结点 
    for(int i = 1;i <= n;i++)f[i] = inf,w[i] = {a[i],g[i],i,0,0};
    
    
    sort(w+1,w+2+n);
    for(int i = 1;i <= n+1;i++){
        if(w[i].g == -1 || w[i].g == ans)continue;
        cnt = 0;
        for(int j = i;w[j].g <= w[i].g + 1 && j <= n+1;j++){
            s1[++cnt] = w[j];
            if(w[j].g == w[i].g)s1[cnt].f = 0;
            else s1[cnt].f = 1;
        }//根据g分层dp 
        sort(s1+1,s1+cnt+1,cmp1);
        CDQ(1,cnt);
        int j = i;
        for(j = i;w[j].g == w[i].g && j <= n+1;j++);
        i = j-1;
    }
    for(int i = 1;i <= n;i++)
        if(g[i] == ans)s = min(s,f[i]+(A[i]+1+n+a[i]) * (n-i) / 2);
    printf("%lld %lld\n",ans,s);

	return 0;

}