您的位置:首页 > 其它

BZOJ4358: permu

2015-12-23 18:40 351 查看

Description

给出一个长度为n的排列P(P1,P2,...Pn),以及m个询问。每次询问某个区间[l,r]中,最长的值域
连续段长度。

Input

第一行两个整数n,m。
接下来一行n个整数,描述P。
接下来m行,每行两个整数l,r,描述一组询问。

Output

对于每组询问,输出一行一个整数,描述答案。

Sample Input

8 3

3 1 7 2 5 8 6 4

1 4

5 8

1 7

Sample Output

3

3

4

HINT

对于询问[1,4],P2,P4,P1组成最长的值域连续段[1,3];

对于询问[5,8],P8,P5,P7组成最长的值域连续段[4,6];

对于询问[1,7],P5,P7,P3,P6组成最长的值域连续段[5,8]。

1<=n,m<=50000

首先O(N^1.5*logN)的莫队套线段树做法应该是谁都会的。

#include<cstdio>
#include<cctype>
#include<queue>
#include<cmath>
#include<cstring>
#include<algorithm>
#define rep(i,s,t) for(int i=s;i<=t;i++)
#define dwn(i,s,t) for(int i=s;i>=t;i--)
#define ren for(int i=first[x];i;i=next[i])
using namespace std;
const int BufferSize=1<<16;
char buffer[BufferSize],*head,*tail;
inline char Getchar() {
if(head==tail) {
int l=fread(buffer,1,BufferSize,stdin);
tail=(head=buffer)+l;
}
return *head++;
}
inline int read() {
int x=0,f=1;char c=Getchar();
for(;!isdigit(c);c=Getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=Getchar()) x=x*10+c-'0';
return x*f;
}
const int maxn=50010;
int n,m,A[maxn],bl[maxn],en[maxn],ans[maxn];
struct Query {
int l,r,id;
bool operator < (const Query& ths) const {
if(bl[l]==bl[ths.l]) return r<ths.r;
return l<ths.l;
}
}Q[maxn];
int findset(int* pa,int x) {return pa[x]==x?x:pa[x]=findset(pa,pa[x]);}
int pa[maxn],s[maxn],vis[maxn],nowans;
void add(int u) {
int v;s[u]=1;pa[u]=u;
if(v=findset(pa,u-1)) pa[v]=u,s[u]+=s[v];
if(v=findset(pa,u+1)) pa[v]=u,s[u]+=s[v];
nowans=max(nowans,s[u]);
}
int pa2[maxn],mx[maxn],mn[maxn],S[maxn],top;
void add2(int u,int& res) {
int v;pa2[u]=u;mx[u]=mn[u]=u;S[++top]=u;
if(v=findset(pa2,u-1)) mn[u]=mn[v];
else if(v=findset(pa,u-1)) mn[u]-=s[v];
if(v=findset(pa2,u+1)) mx[u]=mx[v];
else if(v=findset(pa,u+1)) mx[u]+=s[v];
res=max(res,mx[u]-mn[u]+1);
S[++top]=mx[u];pa2[mx[u]]=u;
S[++top]=mn[u];pa2[mn[u]]=u;
}
int main() {
n=read();m=read();int SIZE=(int)sqrt(n);
rep(i,1,n) A[i]=read(),bl[i]=(i-1)/SIZE+1,en[bl[i]]=i;
rep(i,1,m) Q[Q[i].id=i].l=read(),Q[i].r=read();
sort(Q+1,Q+m+1);
rep(i,1,m) {
int p=i,cur;nowans=0;
while(bl[Q[p].l]==bl[Q[i].l]&&p<=m) p++;
memset(pa,0,sizeof(pa));
cur=en[bl[Q[i].l]];
rep(j,i,p-1) {
while(cur<Q[j].r) add(A[++cur]);
ans[Q[j].id]=nowans;
rep(k,Q[j].l,min(Q[j].r,en[bl[Q[i].l]])) add2(A[k],ans[Q[j].id]);
while(top) pa2[S[top--]]=0;
}
i=p-1;
}
rep(i,1,m) printf("%d\n",ans[i]);
return 0;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: