zoukankan      html  css  js  c++  java
  • P4364 [九省联考2018]IIIDX 题解

    Luogu
    Solution Link

    Description.

    给定一棵树,第 \(i\) 个点的父亲是 \(\lfloor\frac ik\rfloor\)
    有一些权值,你需要对每个节点附上一个权值,满足每个点都比他所有后代小,使得权值构成的序列字典序最大。

    Solution.

    逐位确定。
    \(i\) 位填完后,相当于多了一个限制,就是至少有 \(sz_i-1\) 个数 \(\ge b_i\)
    注意这个限制在一个节点所有孩子被确定后会消失,因为都变成了孩子自己的限制了。

    考虑维护这件事情:

    • 插入一个形如要至少有 \(k\) 个数 \(\ge b\) 的限制
    • 删除一个限制
    • 找到一个最大的可以被取的数
    • 删掉一个数

    考虑 \(f_i\) 表示只考虑 \(b\ge i\) 的限制有多少个可以取。
    则初始就是出现个数的后缀和。
    我们每次要找到一个最后面的满足 \(f_i\ge sz\),这个可以线段树二分,维护前缀 \(\min\)
    多一个限制相当于前缀减 \(k\),少一个数相当于前缀减 \(1\)
    然后就做完了。

    Coding.

    点击查看代码
    //是啊……你就是那只鬼了……所以被你碰到以后,就轮到我变成鬼了{{{
    #include<bits/stdc++.h>
    using namespace std;typedef long long ll;
    template<typename T>inline void read(T &x)
    {
    	x=0;char c=getchar(),f=0;
    	for(;c<'0'||c>'9';c=getchar()) if(c=='-') f=1;
    	for(;c>='0'&&c<='9';c=getchar()) x=(x<<1)+(x<<3)+(c^48);
    	if(f) x=-x;
    }
    template<typename T,typename...L>inline void read(T &x,L&...l) {read(x),read(l...);}//}}}
    const int N=500005;double k;
    int n,ut,w[N],fa[N],tn[N],rs[N],sz[N],tg[N],cn[N];
    namespace segment
    {
    	struct seg{int mn,tg;}T[N<<2];
    	inline void pushup(int x) {T[x].mn=min(T[x<<1].mn,T[x<<1|1].mn);}
    	inline void allc(int x,int w) {T[x].mn+=w,T[x].tg+=w;}
    	inline void pushdw(int x) {if(T[x].tg) allc(x<<1,T[x].tg),allc(x<<1|1,T[x].tg),T[x].tg=0;}
    	inline void build(int x,int l,int r)
    	{
    		if(l==r) return T[x].mn=cn[l],void();
    		build(x<<1,l,(l+r)>>1),build(x<<1|1,((l+r)>>1)+1,r),pushup(x);
    	}
    	inline void modif(int x,int l,int r,int dl,int dr,int dc)
    	{
    		if(l>dr||dl>r) return;else if(dl<=l&&r<=dr) return allc(x,dc);else pushdw(x);
    		modif(x<<1,l,(l+r)>>1,dl,dr,dc),modif(x<<1|1,((l+r)>>1)+1,r,dl,dr,dc),pushup(x);
    	}
    	inline int query(int x,int l,int r,int k)
    	{
    		if(l==r) return l;else pushdw(x);
    		if(T[x<<1].mn<k) return query(x<<1,l,(l+r)>>1,k);
    		else return query(x<<1|1,((l+r)>>1)+1,r,k);
    	}
    	inline int qry(int w) {return T[1].mn>=w?ut:query(1,1,ut,w)-1;}
    	inline void debug(int x,int l,int r)
    	{
    		if(l==r) return printf("%d ",T[x].mn),void();else pushdw(x);
    		debug(x<<1,l,(l+r)>>1),debug(x<<1|1,((l+r)>>1)+1,r);
    	}
    }using namespace segment;
    int main()
    {
    	read(n),scanf("%lf",&k);for(int i=1;i<=n;i++) read(w[i]),sz[i]=1;
    	for(int i=1;i<=n;i++) fa[i]=int(i/k),tn[++ut]=w[i];
    	sort(tn+1,tn+ut+1),ut=unique(tn+1,tn+ut+1)-tn-1;
    	for(int i=1;i<=n;i++) ++cn[w[i]=lower_bound(tn+1,tn+ut+1,w[i])-tn];
    	for(int i=ut;i>=1;i--) cn[i]+=cn[i+1];
    	sz[0]=1;for(int i=n;i>=1;i--) sz[fa[i]]+=sz[i];
    	//for(int i=0;i<=n;i++) printf("%d%c",sz[i],i==n?'\n':' ');
    	tg[0]=1,build(1,1,ut);
    	for(int i=1,v;i<=n;i++)
    	{
    		if(!tg[fa[i]]) modif(1,1,ut,1,rs[fa[i]],sz[fa[i]]-1),tg[fa[i]]=1;
    		//debug(1,1,ut),putchar('\n');
    		rs[i]=v=qry(sz[i]),modif(1,1,ut,1,v,-sz[i]);
    		//printf("! %d ( %d %d\n",v,i,sz[i]);
    	}
    	for(int i=1;i<=n;i++) printf("%d%c",tn[rs[i]],i==n?'\n':' ');
    	return 0;
    }
    
  • 相关阅读:
    搜索优化
    ETL(Extract-Transform-Load的缩写,即数据抽取、转换、装载的过程)
    Tomcat7.0.22在Windows下详细配置过程
    maven 安装配置
    Venus wiki
    搜索引擎基本原理及实现技术——用户查询意图分析
    sql 表自连接
    select 多表查询
    select 嵌套
    Ioc和Aop扩展--多种方式实现依赖注入(构造注入,p命名空间注入,集合类型注入,注入null和注入空值)
  • 原文地址:https://www.cnblogs.com/pealfrog/p/15441263.html
Copyright © 2011-2022 走看看