[貪心 線段樹] LOJ#2472. 「九省聯考 2018」IIIDX
阿新 • • 發佈:2019-02-19
從1到n列舉,逐位確定。
首先可以把關係樹建出來,一個點的權值要大於等於父節點的權值。
如果沒有相同數字的,第 以及它子樹種的點會選擇 這個區間裡的數,選完後把這個區間刪去,繼續考慮
如果有重複的數字,那麼第 個點會選擇第 大的數字,但是它的子樹中的點選擇的區間就不能確定。
令 表示大於等於 的可以選擇的數的個數, 表示已經選了多少個大於等於 的數
那麼如果當前考慮 點, 點選擇的數為 ( 肯定會盡可能的大),那麼我們就會選擇 個大於等於 的數。
可以發現,如果 能選擇 ,那麼對於任何一個小於等於 的 都滿足
也就是 ,用線段樹記錄 ,然後線上段樹上二分一下 就可以了
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <vector>
#define ALL(x) (x).begin(),(x).end()
using namespace std;
typedef pair<int,int> pii;
const int N=500010;
int n,cnt,b[N],a[N],G[N],size[N],ans[N],son[N],dpt[N],fa[N];
double k;
struct edge{
int t,nx;
}E[N];
vector<int> sb;
inline void addedge(int x,int y){
E[++cnt].t=y; E[cnt].nx=G[x]; G[x]=cnt;
}
void dfs(int x){
size[x]=1 ;
for(int i=G[x];i;i=E[i].nx){
dpt[E[i].t]=dpt[x]+1;
dfs(E[i].t);
size[x]+=size[E[i].t];
fa[E[i].t]=x;
}
}
int mn[N<<2],tag[N<<2];
inline void Up(int g){
mn[g]=min(mn[g<<1]+tag[g<<1],mn[g<<1|1]+tag[g<<1|1]);
}
void build(int g,int l,int r){
if(l==r) return mn[g]=b[l],void();
int mid=l+r>>1;
build(g<<1,l,mid); build(g<<1|1,mid+1,r);
Up(g);
}
vector<int> Q[N];
void Modify(int g,int l,int r,int L,int R,int x){
if(l==L && r==R) return tag[g]+=x,void();
int mid=L+R>>1;
if(r<=mid) Modify(g<<1,l,r,L,mid,x);
else if(l>mid) Modify(g<<1|1,l,r,mid+1,R,x);
else Modify(g<<1,l,mid,L,mid,x),Modify(g<<1|1,mid+1,r,mid+1,R,x);
Up(g);
}
int Query(int s){
int g=1,l=1,r=n,ret;
while(l<r){
int mid=l+r>>1; s-=tag[g];
if(mn[g<<1]+tag[g<<1]<s) r=mid,g=g<<1;
else l=mid+1,g=g<<1|1,ret=mid;
}
if(mn[g]+tag[g]>=s) return l;
return ret;
}
int main(){
scanf("%d%lf",&n,&k);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]),sb.push_back(a[i]);
sb.push_back(0); sort(ALL(sb)); sb.erase(unique(ALL(sb)),sb.end());
for(int i=1;i<=n;i++) a[i]=lower_bound(ALL(sb),a[i])-sb.begin();
for(int i=1;i<=n;i++) addedge(i/k,i);
dfs(0);
for(int i=1;i<=n;i++) b[a[i]]++;
for(int i=n;i;i--) b[i]+=b[i+1];
build(1,1,n);
for(int i=1;i<=n;i++) Q[dpt[i]].push_back(i);
for(int d=1;d<=dpt[n];d++){
for(int i=0;i<Q[d].size();i++){
if(d>1 && (i==0 || fa[Q[d][i]]!=fa[Q[d][i-1]]))
Modify(1,1,ans[fa[Q[d][i]]],1,n,size[fa[Q[d][i]]]-1);
int u=Q[d][i],p=Query(size[u]);
ans[u]=p; Modify(1,1,p,1,n,-size[u]);
}
}
for(int i=1;i<=n;i++) printf("%d ",sb[ans[i]]);
return 0;
}