题解 P4747 【[CERC2017]Intrinsic Interval】
这题真的是一道思维好题。(感谢
首先显而易见的有这个好区间的
我们发现包含着这段区间的好区间可能会有很多吧,考虑两个包着这个区间的好区间这话好绕口啊……)。
于是就可以有这样一个思路,我们维护一个扫描线,把这些区间离线下来,然后想办法找出当前点
其实题面上已经给了我们一个非常好的提示:
若它的一个子串
我们发现把这玩意排序之后相邻的两项差为1对吧,那么这个好区间
在
那么我们现在枚举的是
那么我们该如何在处理询问的时候找出区间内等于
上代码~
#include<iostream>
#include<cstdio>
#include<cstring>
#include<set>
#include<vector>
#define ls(_o) (_o<<1)
#define rs(_o) ((_o<<1)|1)
#define up(_o) maxn[_o]=max(maxn[ls(_o)],maxn[rs(_o)])
using namespace std;
namespace ywy{
inline int get(){
int n=0;char c;while((c=getchar())||23333){
if(c>='0'&&c<='9')break;if(c=='-')goto s;
}n=c-'0';while((c=getchar())||23333){
if(c>='0'&&c<='9')n=n*10+c-'0';else return(n);
}s:while((c=getchar())||23333){
if(c>='0'&&c<='9')n=n*10-c+'0';else return(n);
}
}
void print(int num){
if(num>=10)print(num/10);putchar(num%10+'0');
}
int ansl[100001],ansr[100001];
typedef struct _qj{
int l;int r;int id;
friend bool operator <(const _qj &a,const _qj &b){
if(a.l==b.l)return(a.id<b.id);
return(a.l<b.l);
}
}qj;
set<qj> st;
int ints[100001],pos[100001],maxn[1000001],adds[1000001];
inline void down(int tree){
if(!adds[tree])return;
int cjr=adds[tree];
adds[tree]=0;
adds[ls(tree)]+=cjr;adds[rs(tree)]+=cjr;
maxn[ls(tree)]+=cjr;maxn[rs(tree)]+=cjr;
}
int query(int rl,int rr,int l,int r,int tree,int num){//cout<<tree<<endl;
down(tree);int mid=(l+r)>>1;
if(rl>rr)return(-1);
if(rl==l&&rr==r){
if(maxn[tree]!=num)return(-1);if(l==r)return(l);
if(maxn[rs(tree)]==num)return(query(mid+1,r,mid+1,r,rs(tree),num));
return(query(l,mid,l,mid,ls(tree),num));
}
if(rl>mid)return(query(rl,rr,mid+1,r,rs(tree),num));
if(rr<=mid)return(query(rl,rr,l,mid,ls(tree),num));
int cjr=query(mid+1,rr,mid+1,r,rs(tree),num);
if(cjr!=-1)return(cjr);
return(query(rl,mid,l,mid,ls(tree),num));
}
vector<qj> vec[100001];
void inc(int rl,int rr,int l,int r,int tree){
if(rl==l&&rr==r){
adds[tree]++;maxn[tree]++;return;
}
int mid=(l+r)>>1;down(tree);
if(rl>mid)inc(rl,rr,mid+1,r,rs(tree));else{
if(rr<=mid)inc(rl,rr,l,mid,ls(tree));else{
inc(rl,mid,l,mid,ls(tree));
inc(mid+1,rr,mid+1,r,rs(tree));
}
}up(tree);
}
void build(int l,int r,int tree){
if(l==r){
maxn[tree]=l;return;
}
int mid=(l+r)>>1;
build(l,mid,ls(tree));
build(mid+1,r,rs(tree));up(tree);
}
typedef set<qj>::iterator it;
void ywymain(){
int n=get();
for(register int i=1;i<=n;i++)pos[ints[i]=get()]=i;
int m=get();
for(register int i=1;i<=m;i++){
int l=get(),r=get();
qj cjr;cjr.l=l;cjr.r=r;cjr.id=i;
vec[r].push_back(cjr);
}
build(1,n,1);
for(register int i=1;i<=n;i++){
if(ints[i]!=1&&pos[ints[i]-1]<i)inc(1,pos[ints[i]-1],1,n,1);
if(ints[i]!=n&&pos[ints[i]+1]<i)inc(1,pos[ints[i]+1],1,n,1);
for(register int j=0;j<vec[i].size();j++){
st.insert(vec[i][j]);
}
while(st.begin()!=st.end()){
it lp=st.end();lp--;qj me=*lp;
int cjr=query(1,me.l,1,n,1,i);
if(cjr==-1)break;
ansl[me.id]=cjr;
ansr[me.id]=i;st.erase(lp);
}
}
for(register int i=1;i<=m;i++)print(ansl[i]),putchar(' '),print(ansr[i]),putchar('\n');
}
}
int main(){
ywy::ywymain();return(0);//再见程序
}