hdu 3564 树状数组的灵活应用

来源:互联网 发布:js给div加class属性 编辑:程序博客网 时间:2024/05/16 10:31

注释在代码中

两个树状数组,或者用两次

第一次维护的是空位的位置,update,更新管辖范围内空位的个数,getk获得第k个空位置的个数,其实就是第k小数,然后占据该位置,更新相应信息
第二次维护的是最长不下降子序列的长度,update:更新长度,getm:获得当前位置之前的最长的LIS长度,再把当前的数加进末尾

View Code
#include<stdio.h>
#include<string.h>
#define lowbit(i) (i&(-i))
const int MAXN=100005;
const int MAXLOG=17;
int B[MAXN],pos[MAXN];
int N;
void update(int i,int value){ //维护空位的个数
for(;i<=N;i+=lowbit(i))
B[i]+=value;
}
int getK(int k){//返回第k个空位的下标
int ans=0;
for(int i=MAXLOG;i>=0;i--)
{
ans+=(1<<i);
if(ans>N||B[ans]>=k)
ans-=(1<<i);
else k-=B[ans];
}
return ans+1;
}
void updateM(int i, int value)//维护LIS的长度
{
for(;i<=N;i+=lowbit(i))
if(value>B[i])
B[i]=value;
}
int getM(int i){//i代表位置,往前找最大的长度,i位置的数肯定可以使长度加1
int ans=0;
for (;i>0;i-=lowbit(i))
if(B[i]>ans)ans=B[i];
return ans;
}
int main()
{
int t;
int i,j,k,g=1;
scanf("%d",&t);
while(t--)
{
scanf("%d",&N);
memset(B,0,sizeof(int)*(N+1));
for(i=1;i<=N;i++)
{
scanf("%d",&pos[i]);
update(i,1);
}//初始时有n个空位,从后往前插入
for(i=N;i>=1;i--)
{
pos[i]=getK(pos[i]+1);//第pos[i]+1个空位的位置
update(pos[i],-1);
}
int ans=0;
printf("Case #%d:\n",g++);
memset(B,0,sizeof(int)*(N+1));
for(i=1;i<=N;i++)
{
int len=getM(pos[i]);
if(len+1>ans)ans=len+1;
printf("%d\n",ans);
updateM(pos[i],len+1);
}puts("");
}
return 0;
}

 

原创粉丝点击