ABC393F题解
大概评级:绿。
一看到这种题目,就知道肯定是数据结构题,我们首先用一个众所周知的二分来求出 \(pos\) 数组,\(pos_i\) 表示以 \(i\) 结尾的最长上升子序列的大小,然后将询问离线,弄一个 vector
,命名 \(s\),把询问中每个 \(R_i\) 为 \(i(1 \le i \le n)\) 的询问存进 \(s_i\) 中,然后遍历每个 \(i(1 \le i \le n)\),每次先修改动态开点权值线段树上的点 \(a_i\),将它改为 \(pos_i\),然后遍历 \(s_i\),将 \(s_i\) 中存储的询问全部拿出来,然后查询即可。
总时间复杂度:\(O(n+n \log n+q+q \log q) = O(n \log n+q \log q)\)。
代码:
#include<bits/stdc++.h>
using namespace std;
const int N = 1e7+5;
int a[N];
int low[N];
int pos[N];
struct node
{
int l;
int r;
int ls;
int rs;
int maxx;
}t[N];
struct node1
{
int x;
int y;
};
vector<node1>e[N];
int cnt;
void update(int &rt,int l,int r,int x,int v)
{
if(!rt)
{
rt = ++cnt;
t[rt].l = l;
t[rt].r = r;
}
if(t[rt].l == t[rt].r)
{
t[rt].maxx = max(t[rt].maxx,v);
return;
}
int mid = t[rt].l+t[rt].r>>1;
if(x<=mid)
{
update(t[rt].ls,l,mid,x,v);
}
else
{
update(t[rt].rs,mid+1,r,x,v);
}
t[rt].maxx = max(t[t[rt].ls].maxx,t[t[rt].rs].maxx);
}
int query(int rt,int l,int r)
{
if(!rt)
{
return 0;
}
if(l<=t[rt].l&&t[rt].r<=r)
{
return t[rt].maxx;
}
int mid = t[rt].l+t[rt].r>>1,maxx = 0;
if(l<=mid)
{
maxx = max(maxx,query(t[rt].ls,l,r));
}
if(r>mid)
{
maxx = max(maxx,query(t[rt].rs,l,r));
}
return maxx;
}
int ans[N];
signed main()
{
int n,_,o = 0;
scanf("%d %d",&n,&_);
for(int i = 1;i<=n;i++)
{
scanf("%d",&a[i]);
}
int id = 0;
for(int i = 1;i<=n;i++)
{
if(a[i]>low[id])
{
low[++id] = a[i];
pos[i] = id;
}
else
{
int poss = lower_bound(low+1,low+id+1,a[i])-low;
low[poss] = a[i];
pos[i] = poss;
}
}
for(int i = 1;i<=_;i++)
{
int x,y;
scanf("%d %d",&x,&y);
e[x].push_back({i,y});
}
for(int i = 1;i<=n;i++)
{
update(o,1,1e9,a[i],pos[i]);
for(auto it:e[i])
{
ans[it.x] = query(o,1,it.y);
}
}
for(int i = 1;i<=_;i++)
{
printf("%d\n",ans[i]);
}
return 0;
}
总结:这道题的精髓在于将询问离线。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话