我当时在考场上划水的时候好像乱搞搞了20pts,然后发现一堆同届的都写了55pts的贪心=。=???
那就先说那55pts的贪心吧,这个现在看起来还是非常显然的,就是按题意来每一块是分属一个点的,其实这就是棵树,排序之后从叶子往上递增地放就可以了,挺送的=。=
为什么错了,显然有相同的数的时候可能把一个大点的数放前面也是对的,然后就不优了
1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 using namespace std; 5 const int N=500005,M=2e6+20; 6 int val[N],fth[N],siz[N],lst[N]; 7 int n,minn[M],laz[M],rnk[N]; 8 double k; 9 bool cmp(int x,int y) 10 { 11 return x>y; 12 } 13 void Release(int nde) 14 { 15 if(laz[nde]) 16 { 17 int ls=2*nde,rs=2*nde+1; 18 minn[ls]+=laz[nde],minn[rs]+=laz[nde]; 19 laz[ls]+=laz[nde],laz[rs]+=laz[nde],laz[nde]=0; 20 } 21 } 22 void Create(int nde,int l,int r) 23 { 24 if(l==r) 25 minn[nde]=l; 26 else 27 { 28 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; 29 Create(ls,l,mid),Create(rs,mid+1,r); 30 minn[nde]=min(minn[ls],minn[rs]); 31 } 32 } 33 void Change(int nde,int l,int r,int ll,int rr,int tsk) 34 { 35 if(l>rr||r<ll) 36 return ; 37 else if(l>=ll&&r<=rr) 38 minn[nde]+=tsk,laz[nde]+=tsk; 39 else 40 { 41 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde); 42 Change(ls,l,mid,ll,rr,tsk),Change(rs,mid+1,r,ll,rr,tsk); 43 minn[nde]=min(minn[ls],minn[rs]); 44 } 45 } 46 int Query(int nde,int l,int r,int tsk) 47 { 48 if(l==r) 49 return l+(tsk>minn[nde]); 50 else 51 { 52 int mid=(l+r)/2,ls=2*nde,rs=2*nde+1; Release(nde); 53 return (tsk<=minn[rs])?Query(ls,l,mid,tsk):Query(rs,mid+1,r,tsk); 54 } 55 } 56 int main() 57 { 58 scanf("%d%lf",&n,&k); 59 for(int i=1;i<=n;i++) 60 scanf("%d",&val[i]),siz[i]=1; 61 sort(val+1,val+1+n,cmp); 62 for(int i=n;i;i--) 63 { 64 fth[i]=1.0*i/k,siz[fth[i]]+=siz[i]; 65 if(val[i]==val[i+1]) lst[i]=lst[i+1]+1; 66 } 67 Create(1,1,n); 68 for(int i=1;i<=n;i++) 69 { 70 if(fth[i]!=fth[i-1]) 71 Change(1,1,n,rnk[fth[i]],n,siz[fth[i]]-1); 72 int ans=Query(1,1,n,siz[i]); 73 ans+=lst[ans],lst[ans]++,ans-=lst[ans]-1; 74 rnk[i]=ans,Change(1,1,n,ans,n,-siz[i]); 75 } 76 for(int i=1;i<=n;i++) 77 printf("%d ",val[rnk[i]]); 78 return 0; 79 }
原文地址:https://www.cnblogs.com/ydnhaha/p/10279005.html
时间: 2024-09-30 07:54:04