【刷題】BZOJ 5249 [2018多省省隊聯測]IIIDX
Description
【題目背景】
Osu聽過沒?那是Konano最喜歡的一款音樂遊戲,而他的夢想就是有一天自己也能做個獨特酷炫的音樂遊戲。現在,他在世界知名遊戲公司KONMAI內工作,離他的夢想也越來越近了。這款音樂遊戲內一般都包含了許多歌曲,歌曲越多,玩家越不易玩膩。同時,為了使玩家在遊戲上氪更多的金錢花更多的時間,遊戲一開始一般都不會將所有曲目公開,有些曲目你需要通關某首特定歌曲才會解鎖,而且越晚解鎖的曲目難度越高。
【題目描述】
這一天,Konano接到了一個任務,他需要給正在制作中的遊戲《IIIDX》安排曲目的解鎖順序。遊戲內共有n首曲目,每首曲目都會有一個難度d,遊戲內第i首曲目會在玩家Pass第trunc(i/k)首曲目後解鎖(x為下取整符號)若trunc(i/k)=0,則說明這首曲目無需解鎖。舉個例子:當k=2時,第1首曲目是無需解鎖的(trunc(1/2)=0),第7首曲目需要玩家Pass第trunc(7/2)=3首曲目才會被解鎖。Konano的工作,便是安排這些曲目的順序,使得每次解鎖出的曲子的難度不低於作為條件需要玩家通關的曲子的難度,即使得確定順序後的曲目的難度對於每個i滿足Di≥Dtrunc(i/k)。當然這難不倒曾經在信息學競賽摸魚許久的Konano。那假如是你,你會怎麽解決這份任務呢
Input
第1行1個正整數n和1個小數k,n表示曲目數量,k其含義如題所示。
第2行n個用空格隔開的正整數d,表示這n首曲目的難度。
1 ≤ n ≤ 500000
1 < k ≤ 10^9
1 < d ≤ 10^9
Output
輸出1行n個整數,按順序輸出安排完曲目順序後第i首曲目的難度。
若有多解,則輸出d1最大的;若仍有多解,則輸出d2最大的,以此類推。
Sample Input
4 2.0
114 514 1919 810
Sample Output
114 810 514 1919
Solution
官方題解思路很清楚的
先看60分貪心,條件是 \(D_i\)互不相同
把限制關系抽象成樹,第 \(i\)
個節點的父親是第 \(\lfloor \frac{i}{k} \rfloor\) 個節點,這樣題目就變成了把數安放到一個樹上使得兒子比父親大,同時解還要最大
按樹的後序遍歷從大到小放數字就是最優解
但 \(D_i\) 有相同的時候就不行了
例如:\(k=2,D=\{1,1,1,2\}\)
貪心:\(\{1,1,1,2\}\)
正解:\(\{1,1,2,1\}\)
然後
懶得打字了
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=500000+10;
const double eps=1e-8;
int n,d[MAXN],cnt,e,to[MAXN<<1],nex[MAXN<<1],beg[MAXN],fa[MAXN],size[MAXN],ans[MAXN];
db k;
std::map< int,std::vector<int> > M;
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
#define Mid ((l+r)>>1)
#define ls rt<<1
#define rs rt<<1|1
#define lson ls,l,Mid
#define rson rs,Mid+1,r
struct SEG{
int Mn[MAXN<<2],Ad[MAXN<<2];
inline void PushUp(int rt)
{
Mn[rt]=min(Mn[ls],Mn[rs]);
}
inline void PushDown(int rt)
{
Mn[ls]+=Ad[rt];Mn[rs]+=Ad[rt];
Ad[ls]+=Ad[rt];Ad[rs]+=Ad[rt];
Ad[rt]=0;
}
inline void Build(int rt,int l,int r)
{
if(l==r)Mn[rt]=l;
else
{
Build(lson);Build(rson);
PushUp(rt);
}
}
inline void Update(int rt,int l,int r,int L,int R,int k)
{
if(L<=l&&r<=R)Mn[rt]+=k,Ad[rt]+=k;
else
{
if(Ad[rt])PushDown(rt);
if(L<=Mid)Update(lson,L,R,k);
if(R>Mid)Update(rson,L,R,k);
PushUp(rt);
}
}
inline int Query(int rt,int l,int r,int k)
{
if(l==r)return Mn[rt]>=k?l:l+1;
else
{
if(Ad[rt])PushDown(rt);
if(Mn[rs]>=k)return Query(lson,k);
else return Query(rson,k);
}
}
};
SEG T;
#undef Mid
#undef ls
#undef rs
#undef lson
#undef rson
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char c='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(c!='\0')putchar(c);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
inline void insert(int x,int y)
{
to[++e]=y;
nex[e]=beg[x];
beg[x]=e;
to[++e]=x;
nex[e]=beg[y];
beg[y]=e;
}
inline void dfs(int x,int f)
{
size[x]=1;fa[x]=f;
for(register int i=beg[x];i;i=nex[i])
if(to[i]==f)continue;
else dfs(to[i],x),size[x]+=size[to[i]];
}
int main()
{
read(n);scanf("%lf",&k);
for(register int i=1;i<=n;++i)read(d[i]);
std::sort(d+1,d+n+1,std::greater<int>());
for(register int i=n;i>=1;--i)insert(i,(int)((db)i/k+eps));
dfs(0,-1);
for(register int i=1;i<=n;++i)M[d[i]].push_back(i);
T.Build(1,1,n);
for(register int i=1;i<=n;++i)
{
if(fa[i])T.Update(1,1,n,ans[fa[i]],n,size[i]);
ans[i]=T.Query(1,1,n,size[i]);
std::map< int,std::vector<int> >::iterator it=M.find(d[ans[i]]);
ans[i]=it->second.back();
it->second.pop_back();
T.Update(1,1,n,ans[i],n,-size[i]);
}
for(register int i=1;i<=n;++i)write(d[ans[i]],' ');
puts("");
return 0;
}
【刷題】BZOJ 5249 [2018多省省隊聯測]IIIDX