LOJ # 2472. "Nine provinces exam 2018" IIIDX greedy + segment tree

Obviously, if the words are not repeated figures appear directly greedy fill is correct.   

However, when this greedy duplicate numbers are wrong.      

Abstract issue into a tree is obvious.  

We first of all the number of rows from largest to smallest.  

For the size of $ size [i] $ of $ i $, this is definitely the current election to be elected the first $ size [i] $ large. (To $ x $)  

Then, after completion of selected $ x $, $ obviously must be reserved before x $ $ size [i] $ locations to $ i $.  

So assuming that each point has $ f [i] $ represent the maximum number can fill in the number of pre-$ i $, we obviously choose to meet the $ size [i] <= f [j] $ and a maximum of $ i $.   

The process to find the $ j $ binary tree online segment, and then find the location marked with a flag can be. 

code: 

#include <bits/stdc++.h>    
#define ll long long 
#define lson now<<1 
#define rson now<<1|1     
#define N 500006  
#define setIO(s) freopen(s".in","r",stdin) 
using namespace std;        
int minn[N<<2],tag[N<<2],size[N];    
void build(int l,int r,int now) 
{
	if(l==r)  { minn[now]=l; return; }   
	int mid=(l+r)>>1;  
	build(l,mid,lson),build(mid+1,r,rson);   
	minn[now]=min(minn[lson],minn[rson]);  
}   
void mark(int x,int v) 
{
	tag[x]+=v;   
	minn[x]+=v; 
} 
void pushdown(int now) 
{
	if(tag[now]) 
	{
		mark(lson,tag[now]);  
		mark(rson,tag[now]);  
		tag[now]=0; 
	}
}
void update(int l,int r,int now,int L,int R,int v) 
{    
	if(l>=L&&r<=R)  
	{
		mark(now,v);   
		return; 
	}
	pushdown(now); 
	int mid=(l+r)>>1;   
	if(L<=mid)   
		update(l,mid,lson,L,R,v);  
	if(R>mid)  
		update(mid+1,r,rson,L,R,v);    
	minn[now]=min(minn[lson],minn[rson]);   
}
int query(int l,int r,int now,int k) 
{
	if(l==r)  return minn[now]<k?(l+1):l;  
	int mid=(l+r)>>1;   
	pushdown(now);   
	if(minn[rson]>=k)     
		return query(l,mid,lson,k);  
	else 
		return query(mid+1,r,rson,k);    
}   
int w[N],val[N],nxt[N],fa[N],clr[N],ans[N];     
bool cmp(int a,int b) { return a>b; }    
int main() 
{ 
	// setIO("input");    
	int i,j,n;  
	double tmp;  
	scanf("%d%lf",&n,&tmp);   
	for(i=1;i<=n;++i)     
		scanf("%d",&w[i]);     
	sort(w+1,w+1+n,cmp);              
	for(i=n;i>=1;--i) 
	{
		++size[i];    
		nxt[i]=i;    
		fa[i]=(int)(1.0*i/tmp);     
		size[fa[i]]+=size[i];   
		if(i!=n&&w[i]==w[i+1])  
			nxt[i]=nxt[i+1];  
	}
	build(1,n,1);  
	for(i=1;i<=n;++i) 
	{ 
		if(fa[i]&&!clr[fa[i]])                 
		{ 
			update(1,n,1,ans[fa[i]],n,size[fa[i]]-1);     
			clr[fa[i]]=1;         
		}
		ans[i]=query(1,n,1,size[i]);                    
		ans[i]=nxt[ans[i]];      
		update(1,n,1,ans[i],n,-size[i]);       
	}
	for(i=1;i<=n;++i)  
		printf("%d ",w[ans[i]]);  
	return 0;
}

  

Guess you like

Origin www.cnblogs.com/guangheli/p/12451790.html