comet-0-E(LIS+离散化)

题目链接

https://www.cometoj.com/contest/34/problem/E?problem_id=1477

题解

这题和cf650D很像。。

首先一个点他最多只能使 $LIS$ 加一,所以只需要考虑每个点能不能加一就可以了。。

然后考虑是不是转移关键点。

设当前点为 $i$

如果 $i$ 不是关键点,那么考虑接在 $LIS$ 中,所以要处理 $i$ 之前的转移点的最小值,还要考虑转移点的有效转移区间和与下一个转移点差值等于 $1$ 的情况,然后再丢进优先队列,预处理起来比较恶心。。

如果 $i$ 是关键点,那么 $LIS$ 必定不会增长,那么可以接在他的转移点后面 $(a[pre_i]+1)$ 。还有一个很坑的地方是可以接在 $LIS-1$ 的序列中,所以还要把 $LIS-1$ 的点扣出来,想上面一样再开个优先队列恶心预处理。。

各种细节问题吧,得对拍一下比较好。。




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<complex>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-8
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y)/2
#define NM 100005
#define nm 105
using namespace std;
const double pi=acos(-1);
ll read(){
ll x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}




int n,a[NM],c[NM],b[NM],len,d[NM],ans[NM],v[NM];
int nxt[NM],_v[NM],nx[NM];
struct tmp{
int x,y;
bool operator<(const tmp&o)const{return y>o.y;}
};
priority_queue<tmp>q,_q;
vector<tmp>cnt[NM];



int main(){
//freopen("data.in","r",stdin);
int _=read();while(_--){
n=read();inc(i,1,n)a[i]=read();
inc(i,1,n)v[i]=0,nxt[i]=0,_v[i]=0,cnt[i].clear(),nx[i]=0;
while(!q.empty())q.pop();
while(!_q.empty())_q.pop();
d[len=1]=a[1];c[1]=1;b[1]=1;d[0]=-1;
inc(i,2,n){
if(d[len]<a[i])d[++len]=a[i],c[i]=len,b[i]=len,ans[i]=d[len-1]+1;
else{
int t=lower_bound(d+1,d+1+len,a[i])-d;ans[i]=d[t-1]+1;
d[t]=a[i];c[i]=t;b[i]=t;
}
}
d[len=1]=-a[n];
dec(i,n-1,1){
if(d[len]<-a[i])d[++len]=-a[i],c[i]+=len-1;
else{
int t=lower_bound(d+1,d+1+len,-a[i])-d;
d[t]=-a[i];c[i]+=t-1;
}
}
inc(i,1,n)if(c[i]==len){
v[b[i]]++;
cnt[b[i]].push_back(tmp{i,a[i]});
if(b[i]==len)nxt[i]=n+1;
}
inc(i,1,len)sort(cnt[i].begin(),cnt[i].end());
inc(i,1,len-1){
int t=0,s=0,tot=cnt[i+1].size()-1;
for(tmp&j:cnt[i]){
while(t<=tot&&cnt[i+1][t].y>j.y+1)s=max(s,cnt[i+1][t].x),t++;
nxt[j.x]=s;
}
}
inc(i,1,n)if(c[i]==len-1)cnt[b[i]].push_back(tmp{i,a[i]});
inc(i,1,len)sort(cnt[i].begin(),cnt[i].end());
inc(i,1,len-1){
int t=0,s=0,tot=cnt[i+1].size()-1;
for(tmp&j:cnt[i]){
while(t<=tot&&cnt[i+1][t].y>j.y+1)s=max(s,cnt[i+1][t].x),t++;
nx[j.x]=s;
}
}
//inc(i,1,n)printf("%d ",b[i]);putchar('\n');
//inc(i,1,n)printf("%d ",nxt[i]);putchar('\n');
dec(i,n,1)if(b[i]==1&&c[i]==len&&a[i]>0&&q.empty())q.push(tmp{i,0});
dec(i,n,1)if(b[i]==1&&c[i]>=len-1&&a[i]>0&&_q.empty())_q.push(tmp{i,0});
inc(i,1,n){
if(c[i]==len&&v[b[i]]==1){
while(!_q.empty()&&_q.top().x<=i)_q.pop();
if(!_q.empty())ans[i]=min(ans[i],_q.top().y);
printf("%d %d\n",len,ans[i]);
}else{
while(!q.empty()&&q.top().x<=i)q.pop();
if(q.empty())printf("%d 0\n",len);
else printf("%d %d\n",len+1,q.top().y);
}
if(c[i]==len&&nxt[i])q.push(tmp{nxt[i],a[i]+1});
if(c[i]>=len-1&&nx[i])_q.push(tmp{nx[i],a[i]+1});
}
}
return 0;
}