题目链接:https://nanti.jisuanke.com/t/41303
题目大意:给出一个n个元素的数组A,1<=A[i]<=n,找出n个串S满足5个条件:
1:S[i][1]=i 2:S[i][j]<=S[i][j-1](就是单调不增) 3:S中相邻元素在数组A中的下标绝对值<=k 4:S的字典序最大 5:A中的每个元素只能使用一次。输出每个串的长度
思路:首先一个题目中隐含的条件:A中所有元素不相同,这一点可以从条件1看出来。
然后就是很简单了,由于所有元素不相同,那么我们可以直接贪心的找[pos-k,pos+k]中的最大的<k的数。对于每次找到的数,再记录一下答案,避免重复查找就好了。
ACCode:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
#include<map>
#include<set>
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=1e5+10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)
struct ChairTree{
int Rt[MAXN<<5],Lc[MAXN<<5],Rc[MAXN<<5],Sum[MAXN<<5];
int NodeCnt;
void Build(int l,int r,int rt){
rt=++NodeCnt;
if(l==r) return ;
int mid=(l+r)>>1;
Build(l,mid,Lc[rt]);Build(mid+1,r,Rc[rt]);
}
int Modify(int pos,int l,int r,int rt){
int Nrt=++NodeCnt;
Lc[Nrt]=Lc[rt];Rc[Nrt]=Rc[rt];Sum[Nrt]=Sum[rt]+1;
if(l==r) return Nrt;
int mid=(l+r)>>1;
if(pos<=mid) Lc[Nrt]=Modify(pos,l,mid,Lc[Nrt]);
if(pos>mid) Rc[Nrt]=Modify(pos,mid+1,r,Rc[Nrt]);
return Nrt;
}
int Query(int ql,int qr,int l,int r,int k){//[ql,qr]种找最后一个<=k的元素
if(l==r) return l;
int xl=Sum[Lc[qr]]-Sum[Lc[ql]],xr=Sum[Rc[qr]]-Sum[Rc[ql]];
int mid=(l+r)>>1;
int ans=INF32;
if(mid>=k){//只会出现在[l,mid]
if(xl) ans=Query(Lc[ql],Lc[qr],l,mid,k);
else return ans;
}
else{// mid<k
//[l,mid]和[mid+1,r]都可能出现
if(xr) ans=Query(Rc[ql],Rc[qr],mid+1,r,k);
if(ans!=INF32) return ans;
if(xl) ans=Query(Lc[ql],Lc[qr],l,mid,k);
return ans;
}
}
void Intt(int l,int r){
NodeCnt=0;
Build(l,r,Rt[0]);
}
void Update(int pos,int l,int r,int i){
Rt[i]=Modify(pos,l,r,Rt[i-1]);
}
int Ans(int ql,int qr,int l,int r,int k){//查找最大的<=r的元素
return Query(Rt[ql-1],Rt[qr],l,r,k);
}
};
ChairTree CT;
int A[MAXN],Vis[MAXN];
int Ans[MAXN];
int n,k;
void DFS(int pos){
int val=A[pos];
if(Ans[val]) return ;
int mi=max(1,pos-k),mx=min(n,pos+k);//查询[mi,mx]的最大的<A[pos]元素
int res;
if(val==1) res=INF32;
else res=CT.Ans(mi,mx,1,n,A[pos]-1);
if(res==INF32){
Ans[val]=1;//当前没有更小的了
}
else{
DFS(Vis[res]);//更新更小的
Ans[val]=Ans[res]+1;//resi是可以选择的元素
}
}
int main(){
int T;scanf("%d",&T);
while(T--){
clean(Ans,0);
scanf("%d%d",&n,&k);
for(int i=1;i<=n;++i){
scanf("%d",&A[i]);
Vis[A[i]]=i;
}CT.Intt(1,n);
for(int i=1;i<=n;++i) CT.Update(A[i],1,n,i);
for(int i=1;i<=n;++i) DFS(i);
printf("%d",Ans[1]);
for(int i=2;i<=n;++i) printf(" %d",Ans[i]);printf("\n");
}
}