【题解】CF 193D Two Segments
首先将枚举原排列中的区间转化为枚举值域上的区间。
从小往大对 \(r\) 扫描线,对于每个 \(l\in[1,r)\) 维护将 \([l,r]\) 在原排列中最少要分成多少段。显然只有 \(1\) 或 \(2\) 段才会产生贡献。那么我们用线段树维护值域上的每个 \(l\) 的最小段数,并维护值域区间上的最小值与最小值和最小值加一的数量。考虑加入 \(p_i\),如何影响我们维护的值。首先对于 \(l\in[1,p_i]\),要多出一段。如果 \(p_{i-1}<p_i\),那么对于 \(l\in[1,p_{i-1}]\),会减少一段。\(p_{i+1}\) 同理。直接在线段树上区间修改即可。时间复杂度 \(O(n\log n)\)。
复制代码
- 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
using namespace std;
namespace asbt{
namespace cplx{bool begin;}
const int maxn=3e5+5;
int n,a[maxn],b[maxn],tag[maxn<<2];
struct node{
int zhi,nm1,nm2;
node(int zhi=0,int nm1=0,int nm2=0):zhi(zhi),nm1(nm1),nm2(nm2){}
il node operator+(const node &x)const{
node res(min(zhi,x.zhi));
if(res.zhi==zhi){
res.nm1+=nm1;
res.nm2+=nm2;
}
else if(res.zhi+1==zhi){
res.nm2+=nm1;
}
if(res.zhi==x.zhi){
res.nm1+=x.nm1;
res.nm2+=x.nm2;
}
else if(res.zhi+1==x.zhi){
res.nm2+=x.nm1;
}
return res;
}
}tr[maxn<<2];
il void pushup(int id){
tr[id]=tr[lid]+tr[rid];
}
il void pushtag(int id,int v){
tag[id]+=v,zhi(id)+=v;
}
il void pushdown(int id){
if(tag[id]){
pushtag(lid,tag[id]);
pushtag(rid,tag[id]);
tag[id]=0;
}
}
il void build(int id,int l,int r){
if(l==r){
nm1(id)=1;
return ;
}
int mid=(l+r)>>1;
build(lid,l,mid);
build(rid,mid+1,r);
pushup(id);
}
il void add(int id,int L,int R,int l,int r,int v){
if(l>r){
return ;
}
if(L>=l&&R<=r){
pushtag(id,v);
return ;
}
pushdown(id);
int mid=(L+R)>>1;
if(l<=mid){
add(lid,L,mid,l,r,v);
}
if(r>mid){
add(rid,mid+1,R,l,r,v);
}
pushup(id);
}
il int query(int id,int L,int R,int l,int r){
if(l>r){
return 0;
}
if(L>=l&&R<=r){
int res=0;
if(zhi(id)<=2){
res+=nm1(id);
}
if(zhi(id)<=1){
res+=nm2(id);
}
return res;
}
pushdown(id);
int mid=(L+R)>>1,res=0;
if(l<=mid){
res+=query(lid,L,mid,l,r);
}
if(r>mid){
res+=query(rid,mid+1,R,l,r);
}
return res;
}
namespace cplx{
bool end;
il double usdmem(){return (&begin-&end)/1048576.0;}
}
int main(){
ios::sync_with_stdio(0),cin.tie(0);
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
b[a[i]]=i;
}
ll ans=0;
build(1,1,n);
for(int i=1;i<=n;i++){
add(1,1,n,1,i,1);
if(a[b[i]-1]<i){
add(1,1,n,1,a[b[i]-1],-1);
}
if(a[b[i]+1]<i){
add(1,1,n,1,a[b[i]+1],-1);
}
ans+=query(1,1,n,1,i-1);
}
cout<<ans;
return 0;
}
}
int main(){return asbt::main();}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步