zoukankan      html  css  js  c++  java
  • 【BZOJ5249】【九省联考2018】—IIIDX(线段树)

    传送门

    题意:给你一座森林和一堆权值,要把每个权值分配给点,要保证儿子不小于父亲的权值,问字典序最大的方案

    开始第一眼以为是傻逼题,结果交上去果断挂掉
    因为在有权值相同的情况,比如说n=4,k=2,d=1,1,1,2n=4,k= 2,d=1,1,1,2,答案是1,1,1,21,1,1,2,实际上则是1,1,2,11,1,2,1

    发现每个要要在保证自己最大的情况下是需要给后面的子树“预留”一些节点的,而且自己也要满足别的点的预留情况
    可以用线段树维护一下第ii大的数能给更小的数预留多少
    这样分配的时候可以在线段树上二分找到最大的满足的点

    记得加了一个点后要把它父亲预留的影响去掉

    #include<bits/stdc++.h>
    using namespace std;
    inline int read(){
    	char ch=getchar();
    	int res=0,f=1;
    	while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
    	while(isdigit(ch))res=(res+(res<<2)<<1)+(ch^48),ch=getchar();
    	return res*f;
    }
    const int N=500005;
    int tr[N<<2],tag[N<<2];
    int cnt[N],a[N],pos[N],fa[N],siz[N],n;
    double k;
    #define lc (u<<1)
    #define rc ((u<<1)|1)
    #define mid ((l+r)>>1)
    inline void pushup(int u){
    	tr[u]=min(tr[lc],tr[rc]);
    }
    inline void pushdown(int u){
    	tr[lc]+=tag[u],tr[rc]+=tag[u],tag[lc]+=tag[u],tag[rc]+=tag[u],tag[u]=0;
    }
    void buildtree(int u,int l,int r){
    	if(l==r){tr[u]=l;return;}
    	buildtree(lc,l,mid);
    	buildtree(rc,mid+1,r);
    	pushup(u);
    }
    void update(int u,int l,int r,int st,int des,int p){
    	if(st<=l&&r<=des){
    		tr[u]+=p,tag[u]+=p;return;
    	}
    	pushdown(u);
    	if(st<=mid)update(lc,l,mid,st,des,p);
    	if(mid<des)update(rc,mid+1,r,st,des,p);
    	pushup(u);
    }
    int query(int u,int l,int r,int p){
    	if(l==r)return tr[u]>=p?l:l+1;
    	pushdown(u);
    	if(p<=tr[rc])return query(lc,l,mid,p);
    	else return query(rc,mid+1,r,p);
    }
    inline bool comp(int a,int b){
    	return a>b;
    }
    int main(){
    	n=read(),scanf("%lf",&k);
    	for(int i=1;i<=n;i++)siz[i]=1,a[i]=read();
    	sort(a+1,a+n+1,comp);
    	for(int i=n;i;i--)
    		fa[i]=(int)floor((double)i/k),siz[fa[i]]+=siz[i];
    	cnt[n]=n;
    	for(int i=n-1;i;i--)
    		if(a[i]==a[i+1])cnt[i]=cnt[i+1];else cnt[i]=i;
    	buildtree(1,1,n);
    	for(int i=1;i<=n;i++){
    		if(fa[i]&&fa[i]!=fa[i-1])update(1,1,n,pos[fa[i]],n,siz[fa[i]]-1);
    		int p=cnt[query(1,1,n,siz[i])];
    		cnt[p]++,pos[i]=p;
    		update(1,1,n,p,n,-siz[i]);
    	}
    	for(int i=1;i<=n;i++)cout<<a[pos[i]]<<" ";
    }
    
  • 相关阅读:
    移动端适配问题
    面试题
    c++学习之路
    es6特性
    ndoe安装依赖注意的问题
    如何阻止button默认的刷新页面操作
    npm 全局安装模块,出现XXX不是内部或外部命令解决方法
    .Net MVC系统源码与教学视频《资源分享系列6》
    Javascript书店课程设计《资源分享系列4》
    Python教程与源码《资源分享系列4》
  • 原文地址:https://www.cnblogs.com/stargazer-cyk/p/11145648.html
Copyright © 2011-2022 走看看