版权声明:写得不好,转载请通知一声,还请注明出处,感激不尽 https://blog.csdn.net/As_A_Kid/article/details/88626749
Problem
Solution
队长:这不是WC上讲的析合树吗?
我(懵逼):……?
有一个性质,如果有两个连续区间交叉了,那么它们的交集一定也是连续区间。因为如果它不是,那么中间一定是缺了一个元素,而这两个区间不可能同时拥有这个缺少的元素。
那么对于一个询问,包含它的最短的连续区间,必然是从询问的
端点开始,能包含且
最大的区间。
直接做有点无从下手,把连续区间的定义转化一下,相当于是拥有 个 的数对的区间,不妨记数对个数为 。
考虑枚举右端点,那么我们就要查询满足 的端点,这个怎么维护呢?不难发现这个左边这个值不可能大于 ,因此我们对于这个询问只需要支持查 中的最大的值和出现位置即可。修改 是一个区间修改,线段树支持。
时间复杂度 。
Code
#include <cstdio>
#include <vector>
#include <set>
using namespace std;
typedef long long ll;
const int maxn=100010;
template <typename Tp> inline int getmin(Tp &x,Tp y){return y<x?x=y,1:0;}
template <typename Tp> inline int getmax(Tp &x,Tp y){return y>x?x=y,1:0;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
struct qy{
int l,r,id;
bool operator < (const qy &b)const{return l==b.l?id<b.id:l>b.l;}
}tmp,q[maxn];
struct data{
int mx,pos;
data(const int _mx=0,const int _pos=0){mx=_mx;pos=_pos;}
data operator + (const data &b)const{return mx>b.mx?(*this):b;}
}res,t[maxn<<2];
int n,m,a[maxn],app[maxn],ansl[maxn],ansr[maxn];
int add[maxn<<2];
vector<qy> G[maxn];
vector<qy>::iterator itr;
set<qy> s;
void pushdown(int rt)
{
t[rt<<1].mx+=add[rt];add[rt<<1]+=add[rt];
t[rt<<1|1].mx+=add[rt];add[rt<<1|1]+=add[rt];
add[rt]=0;
}
void build(int l,int r,int rt)
{
if(l==r){t[rt].mx=t[rt].pos=l;return ;}
int m=(l+r)>>1;
build(l,m,rt<<1);build(m+1,r,rt<<1|1);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
void update(int l,int r,int L,int R,int val,int rt)
{
if(L<=l&&r<=R){t[rt].mx+=val;add[rt]+=val;return ;}
int m=(l+r)>>1;
if(add[rt]) pushdown(rt);
if(L<=m) update(l,m,L,R,val,rt<<1);
if(m<R) update(m+1,r,L,R,val,rt<<1|1);
t[rt]=t[rt<<1]+t[rt<<1|1];
}
data query(int l,int r,int L,int R,int rt)
{
if(L<=l&&r<=R) return t[rt];
int m=(l+r)>>1;data res;
if(add[rt]) pushdown(rt);
if(L<=m) res=res+query(l,m,L,R,rt<<1);
if(m<R) res=res+query(m+1,r,L,R,rt<<1|1);
return res;
}
void input()
{
read(n);
for(int i=1;i<=n;i++) read(a[i]);
read(m);
for(int i=1;i<=m;i++)
{
read(q[i].l);read(q[i].r);q[i].id=i;
G[q[i].r].push_back(q[i]);
}
}
int main()
{
input();
build(1,n,1);
for(int i=1;i<=n;i++)
{
app[a[i]]=i;
if(a[i]>1&&app[a[i]-1]) update(1,n,1,app[a[i]-1],1,1);
if(a[i]<n&&app[a[i]+1]) update(1,n,1,app[a[i]+1],1,1);
for(itr=G[i].begin();itr!=G[i].end();++itr) s.insert(*itr);
while(s.begin()!=s.end())
{
tmp=*s.begin();
res=query(1,n,1,tmp.l,1);
if(res.mx<i) break;
ansl[tmp.id]=res.pos;ansr[tmp.id]=i;
s.erase(s.begin());
}
}
for(int i=1;i<=m;i++) printf("%d %d\n",ansl[i],ansr[i]);
return 0;
}