序列
暂且叫这名字,因为考试中它的正式名字为“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;
}
一如既往,万事胜意