序列

暂且叫这名字,因为考试中它的正式名字为“d”,这显然不太好……


  • 题目


先说一下,其实严格上来说这道题我并没有完全写过,这并不能怪我对吧,是数据范围过于不友好,但凡它把数据范围调到 \(10^6\)(就是没有这个2),咱都能过啊……

小小地牢骚一句。

懒得写解析了,反正就那样。题解用的扫描线,然而咱不会,于是只能卑微地写了个线段树,实测当时限放到20s时可以过掉……

我太弱了。

#include<cstdio>
#include<algorithm>
//#define zczc
using namespace std;
const int N=2000010;
const int inf=1e9;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}

bool tree_kind=true;

inline int max(int s1,int s2){
	return s1<s2?s2:s1;
}
inline int min(int s1,int s2){
	return s1<s2?s1:s2;
}
inline void check(int &s1,int s2){
	if(s1<s2)s1=s2;return;
}

#define lc (wh<<1)
#define rc (wh<<1|1)
#define mid (t[wh].l+t[wh].r>>1)
struct node{
	int l,r,data;
}t[N<<2];
inline void pushup(int wh){
	if(tree_kind)t[wh].data=max(t[lc].data,t[rc].data);
	else t[wh].data=min(t[lc].data,t[rc].data);
	return;
}
inline void build(int wh,int l,int r){
	t[wh].l=l,t[wh].r=r;
	t[wh].data=tree_kind?0:inf;
	if(l==r)return;
	build(lc,l,mid);
	build(rc,mid+1,r);
	return;
}
inline void change(int wh,int pl,int val){
	if(t[wh].l==t[wh].r){
		t[wh].data=val;
		return;
	}
	if(pl<=mid)change(lc,pl,val);
	else change(rc,pl,val);
	pushup(wh);
	return;
}
inline int work(int wh,int wl,int wr){
	if(wl<=t[wh].l&&t[wh].r<=wr){
		return t[wh].data;
	}
	int an=tree_kind?0:inf;
	if(wl<=mid){
		if(tree_kind)an=max(an,work(lc,wl,wr));
		else an=min(an,work(lc,wl,wr));
	}
	if(wr>mid){
		if(tree_kind)an=max(an,work(rc,wl,wr));
		else an=min(an,work(rc,wl,wr));
	}
	pushup(wh);
	return an;
}
#undef lc
#undef rc
#undef mid

struct node1{
	int l,r;
}b[N<<1];
inline bool cmp11(node1 s1,node1 s2){
	return s1.l<s2.l;
}
inline bool cmp12(node1 s1,node1 s2){
	return s1.l>s2.l;
}
inline bool cmp13(node1 s1,node1 s2){
	return s1.r>s2.r;
}

struct node2{
	int l,r,pl;
}q[N];
inline bool cmp21(node2 s1,node2 s2){
	return s1.l<s2.l;
}
inline bool cmp22(node2 s1,node2 s2){
	return s1.l>s2.l;
}
inline bool cmp23(node2 s1,node2 s2){
	return s1.r>s2.r;
}

int m,n,a[N],last[N],cnt,ans[N];

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);read(n);
	for(int i=1;i<=m;i++){
		read(a[i]);
		cnt++;
		b[cnt].l=last[a[i]];
		b[cnt].r=i;
		last[a[i]]=i;
	}
	for(int i=1;i<N;i++){
		if(last[i]==0)continue;
		cnt++;
		b[cnt].l=last[i];
		b[cnt].r=m+1;
	}
	for(int i=1;i<=n;i++){
		read(q[i].l);read(q[i].r);
		q[i].pl=i;
	}
	int now;
	
	//两端都在区间内 
	now=1;
	build(1,0,m+1);
	sort(b+1,b+cnt+1,cmp12);
	sort(q+1,q+n+1,cmp22);
	for(int i=1;i<=n;i++){
		while(now<=cnt&&b[now].l>=q[i].l){
			change(1,b[now].r,b[now].r-b[now].l-1);
			now++;
		}
		check(ans[q[i].pl],work(1,q[i].l,q[i].r));
	}
	
	//左端点到某个值
	now=1;
	build(1,0,m+1);
	sort(b+1,b+cnt+1,cmp11);
	sort(q+1,q+n+1,cmp21);
	for(int i=1;i<=n;i++){
		while(now<=cnt&&b[now].l<q[i].l){
			change(1,b[now].r,b[now].r);
			now++;
		}
		check(ans[q[i].pl],work(1,q[i].l,q[i].r)-q[i].l);
	}
	
	//右端点到某个值
	now=1;tree_kind=false;
	build(1,0,m+1);
	sort(b+1,b+cnt+1,cmp13);
	sort(q+1,q+n+1,cmp23);
	for(int i=1;i<=n;i++){
		while(now<=cnt&&b[now].r>q[i].r){
			change(1,b[now].l,b[now].l);
			now++;
		}
		check(ans[q[i].pl],q[i].r-work(1,q[i].l,q[i].r));
	}
	
	for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
	
	return 0;
}
posted @ 2021-11-18 20:31  Feyn618  阅读(11)  评论(0编辑  收藏  举报