codeforces#343 D. Babaei and Birthday Cake

dp+线段树优化,水题

有几个要注意的地方,首先是注意到Pi可以提出来,所以不用double,降低进度误差;接着考虑提出来后会不会爆longlong,最大情况n*a[i]=n*r*r*h=1e5*1e4*1e4*1e4=1e17,显然不会,于是就可以愉快地用longlong了。。

被自己蠢哭了。。。挂精度挂了半天居然没看出来这个。。。

接着还是写下思路吧。。设dp[i]为以a[i]为结尾的可获得的最大体积,显然,dp[i]=max(dp[j]+a[i]) (a[j]<a[i]) 。这是个n^2的,注意到a[j]<a[i],于是用线段树统计下(0,a[i])的dp的最大值就可以了,离散化之后是1~a[i]-1。

调了一晚上最后发现最后一项忘记加进去了。。。。

#include<bits/stdc++.h>
#define REP(i,a,b) for(int i=a;i<=b;i++)
#define MS0(a) memset(a,0,sizeof(a))
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

using namespace std;

typedef long long ll;
const int maxn=1000100;
const int INF=1e9+10;
const double Pi=acos(-1.0);
const double EPS=1e-7;

int n;
int r,h;
ll a[maxn],X[maxn];int Xn;
int b[maxn];
ll Max[maxn];

void push_up(int rt)
{
    Max[rt]=max(Max[rt<<1],Max[rt<<1|1]);
}

void build(int l,int r,int rt)
{
    if(l==r){
        Max[rt]=0;
        return;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    push_up(rt);
}

void update(int p,ll c,int l,int r,int rt)
{
    if(l==r){
        Max[rt]=c;
        return;
    }
    int m=(l+r)>>1;
    if(p<=m) update(p,c,lson);
    else update(p,c,rson);
    push_up(rt);
}

ll query(int L,int R,int l,int r,int rt)
{
    if(L>R) return 0;
    if(L<=l&&r<=R) return Max[rt];
    int m=(l+r)>>1;
    ll res=0;
    if(L<=m) res=max(res,query(L,R,lson));
    if(R>m) res=max(res,query(L,R,rson));
    return res;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
    #endif // ONLINE_JUDGE
    while(cin>>n){
        REP(i,1,n) scanf("%d%d",&r,&h),X[i]=a[i]=1LL*r*r*h;
        sort(X+1,X+n+1);
        Xn=unique(X+1,X+n+1)-(X+1);
        REP(i,1,n) b[i]=lower_bound(X+1,X+Xn+1,a[i])-X;
        build(1,Xn,1);
        ll ans;
        REP(i,1,n){
            ll tmp=query(1,b[i]-1,1,Xn,1)+a[i];
            update(b[i],tmp,1,Xn,1);/// change not add
        }
        printf("%.12f
",Pi*Max[1]);
    }
    return 0;
}
View Code
没有AC不了的题,只有不努力的ACMER!
原文地址:https://www.cnblogs.com/--560/p/5205807.html