动态规划专题
醉了醉了,
Question_A
这一题我硬生生学了三个小时,才勉强看到,树状数组太难理解了,主要是不知道怎么样,他是干什么的;
贴链接贴链接:(树状数组链接)
https://blog.csdn.net/rentenglong2012/article/details/69230308
https://blog.csdn.net/cww97/article/details/50706879
题解:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int ip[20008][6];
int a[100008];
int b[100008];
int c[100008];
int n;
//int num[20008];
int query(int x){
int ans=0;
while(x>0){
ans=max(ans,c[x]);
x-=( x&-x );
}
return ans;
}
void updata(int x,int y){
while(x<=5*n){
c[x]=max(c[x],y);
x+=( x&-x );
}
}
int main(){
memset(ip,0,sizeof(ip));
scanf("%d",&n);
for(int i=1;i<=5*n;i++){
scanf("%d",&a[i]);
ip[ a[i] ][ ++ip[a[i]][0] ]=i;
}
for(int i=1;i<=5*n;i++)
scanf("%d",&b[i]);
for(int i=1;i<=5*n;i++){
for(int j=5;j>0;j--){
int t=ip[b[i]][j];
updata(t,query(t-1)+1);
}
}
printf("%d\n",query(5*n));
}
Question_N
单调队列算法;挺好理解的,模板代码;
#include<cstring>
#include<cstdio>
int n,k;
int num[1000008];
int q[1000008];
int ip[1000008];
void getMin(){
memset(q,0,sizeof(q));
memset(ip,0,sizeof(ip));
int head=1,tail=0,flag=1;
for(int i=0;i<k-1;i++){
while(tail>=head && q[tail]>num[i])
tail--;
q[++tail]=num[i];
ip[tail]=i;
}
for(int i=k-1;i<n;i++){
while(tail>=head && q[tail]>num[i])
tail--;
q[++tail]=num[i];
ip[tail]=i;
if(ip[head]<i-k+1)
head++;
if(flag){
printf("%d",q[head]);
flag=0;
}
else
printf(" %d",q[head]);
}
printf("\n");
}
void getMax(){
memset(q,0,sizeof(q));
memset(ip,0,sizeof(ip));
int head=1,tail=0,flag=1;
for(int i=0;i<k-1;i++){
while(tail>=head && q[tail]<=num[i])
tail--;
q[++tail]=num[i];
ip[tail]=i;
}
for(int i=k-1;i<n;i++){
while(tail>=head && q[tail]<=num[i])
tail--;
q[++tail]=num[i];
ip[tail]=i;
if(ip[head]<i-k+1)
head++;
if(flag){
printf("%d",q[head]);
flag=0;
}
else
printf(" %d",q[head]);
}
}
int main(){
scanf("%d%d",&n,&k);
for(int i=0;i<n;i++)
scanf("%d",&num[i]);
getMin();
getMax();
}