Chef and Deforestation CodeChef
阿新 • • 發佈:2018-12-14
對於在xi處 高度為hi的一棵樹 令hi-=xi 將問題轉換為求h相同的兩點之間有多少點的值大於h
比如減完x後 高為h的樹有p1 p2 p3...pk這幾棵 在p1於p3之間連繩子相當於在p1p2之間 p2p3之間連繩子的加值之和 所以對於同一高度的樹 就是個最大子段和問題 至於求h相同的兩點之間有多少點的值大於h 主席樹搞一搞
#include <bits/stdc++.h> using namespace std; typedef long long ll; const double N=1000000000000000000.0; const int maxn=250010; struct node1 { ll x,h; }; struct node2 { int l,r; ll val,cnt; }; vector <int> pre[maxn]; node1 ary[maxn]; node2 tree[20*maxn]; double gou[maxn]; ll tmp[maxn]; int root[maxn]; int n,len,num; bool cmp(node1 n1,node1 n2) { return n1.x<n2.x; } int build(int l,int r) { int cur,m; cur=num++; tree[cur].l=tree[cur].r=0; tree[cur].val=tree[cur].cnt=0; if(l==r) return cur; m=(l+r)/2; tree[cur].l=build(l,m); tree[cur].r=build(m+1,r); return cur; } int update(int rot,int tar,ll val,int l,int r) { int cur,m; cur=num++; tree[cur]=tree[rot]; tree[cur].val+=val,tree[cur].cnt++; if(l==r) return cur; m=(l+r)/2; if(tar<=m) tree[cur].l=update(tree[rot].l,tar,val,l,m); else tree[cur].r=update(tree[rot].r,tar,val,m+1,r); return cur; } void query(int lrot,int rrot,ll &res1,ll &res2,int pl,int pr,int l,int r) { int m; if(pl<=l&&r<=pr) { res1+=(tree[rrot].val-tree[lrot].val); res2+=(tree[rrot].cnt-tree[lrot].cnt); return; } m=(l+r)/2; if(pl<=m) query(tree[lrot].l,tree[rrot].l,res1,res2,pl,pr,l,m); if(pr>m) query(tree[lrot].r,tree[rrot].r,res1,res2,pl,pr,m+1,r); } int main() { double c,ans,minn,t1,t2; ll res1,res2; int t,i,j,p; c=sqrt(2.0); scanf("%d",&t); while(t--) { scanf("%d",&n); for(i=1;i<=n;i++) { scanf("%lld%lld",&ary[i].x,&ary[i].h);//sort ary[i].h-=ary[i].x; //tmp[i]=h[i]; } sort(ary+1,ary+n+1,cmp); for(i=1;i<=n;i++) tmp[i]=ary[i].h; /* for(i=1;i<=n;i++) printf("%lld ",h[i]); printf("\n"); */ sort(tmp+1,tmp+n+1); len=unique(tmp+1,tmp+n+1)-tmp-1; for(i=1;i<=len;i++) pre[i].clear(); num=0; root[0]=build(1,len); for(i=1;i<=n;i++) { p=lower_bound(tmp+1,tmp+len+1,ary[i].h)-tmp; pre[p].push_back(i); root[i]=update(root[i-1],p,ary[i].h,1,len); } /* for(i=1;i<=len;i++) { printf("**") } */ ans=-N; for(i=1;i<=len;i++) { for(j=0;j+1<pre[i].size();j++) { t1=ary[pre[i][j+1]].x-ary[pre[i][j]].x; t1*=c; p=lower_bound(tmp+1,tmp+len+1,ary[pre[i][j]].h)-tmp; if(p+1<=len) { res1=0,res2=0; query(root[pre[i][j]-1],root[pre[i][j+1]],res1,res2,p+1,len,1,len); t2=res1-res2*tmp[p]; } else t2=0.0; gou[j]=t1-t2; } minn=0.0; for(j=0;j+1<pre[i].size();j++) { if(j>0) gou[j]+=gou[j-1]; ans=max(ans,gou[j]-minn); /* if(ans<gou[j]-minn) { printf("%d %d\n",pre[i][j],pre[i][j+1]); ans=gou[j]-minn; } */ minn=min(minn,gou[j]); } } if(ans!=-N) printf("%.8f\n",ans); else printf("-1\n"); } return 0; } /* 1 3 1 1 2 5 3 3 1 6 2 1 4 11 3 10 6 10 5 4 7 6 1 4 2 1 6 10 5 4 7 6 */