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\n",Pi*Max[1]); } return 0; }
没有AC不了的题,只有不努力的ACMER!