bzoj4358 perm

4358: permu

Time Limit: 30 Sec  Memory Limit: 512 MB

Submit: 327  Solved: 98

[Submit][Status][Discuss]

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

Source

By sumix173

思路很棒!

每个点记录两个信息:f[i][j]表示i的子树中深度为j的节点的个数。g[i][j]表示满足d[a]-2*d[lca(a,b)]=d[b]-2*d[lca(a,b)]的二元点对(a,b)的个数。

从下向上启发式合并,每次将轻儿子的信息合并到重儿子上,总的时间复杂度为O(nlogn)。在合并的过程中同时计算出答案。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<stack>
#define F(i,j,n) for(int i=j;i<=n;i++)
#define D(i,j,n) for(int i=j;i>=n;i--)
#define ll long long
#define pa pair<int,int>
#define maxn 50005
#define inf 1000000000
using namespace std;
int n,m,block,l,r,mx;
int a[maxn],pos[maxn],pl[maxn],pr[maxn],ans[maxn];
bool vst[maxn];
stack<pa> st;
struct data{int l,r,id;}b[maxn];
inline int read()
{
	int x=0,f=1;char ch=getchar();
	while (ch<'0'||ch>'9'){if (ch=='-') f=-1;ch=getchar();}
	while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
inline bool cmp(data x,data y)
{
	return pos[x.l]==pos[y.l]?x.r<y.r:x.l<y.l;
}
inline bool cmp_id(data x,data y)
{
	return x.id<y.id;
}
inline void add(int x,int flg)
{
	vst[x]=true;
	int tl=x,tr=x;
	if (vst[x-1]) tl=pl[x-1];
	if (vst[x+1]) tr=pr[x+1];
	if (flg)
	{
		st.push(make_pair(tl,pr[tl]));
		st.push(make_pair(tr,pl[tr]));
	}
	pr[tl]=tr;pl[tr]=tl;
	mx=max(mx,tr-tl+1);
}
inline int query(int l,int r)
{
	memset(vst,false,sizeof(vst));
	memset(pl,0,sizeof(pl));
	memset(pr,0,sizeof(pr));
	mx=0;
	F(i,l,r) add(a[i],0);
	return mx;
}
int main()
{
	n=read();m=read();
	block=int(sqrt(n));
	F(i,1,n) a[i]=read();
	F(i,1,n) pos[i]=(i-1)/block+1;
	F(i,1,m)
	{
		b[i].l=read();b[i].r=read();b[i].id=i;
		if (pos[b[i].l]==pos[b[i].r])
		{
			ans[i]=query(b[i].l,b[i].r);
			b[i].l=0;
		}
	}
	sort(b+1,b+m+1,cmp);
	F(i,1,m) if (b[i].l)
	{
		if (pos[b[i].l]!=pos[b[i-1].l])
		{
			l=pos[b[i].l]*block;
			r=l-1;
			mx=0;
			memset(vst,false,sizeof(vst));
			memset(pl,0,sizeof(pl));
			memset(pr,0,sizeof(pr));
		}
		for(;r<b[i].r;r++) add(a[r+1],0);
		int tmp=mx;
		D(j,l-1,b[i].l) add(a[j],1);
		ans[b[i].id]=mx;
		mx=tmp;
		D(j,l-1,b[i].l) vst[a[j]]=false;
		while (!st.empty())
		{
			pl[st.top().first]=st.top().second;st.pop();
			pr[st.top().first]=st.top().second;st.pop();
		}
	}
	F(i,1,m) printf("%d\n",ans[i]);
	return 0;
}
时间: 2024-08-09 06:47:57

bzoj4358 perm的相关文章

全排列问题的递归算法(Perm)

[题目]设计一个递归算法生成n个元素{r1,r2,-,rn}的全排列. [算法讲解] 设R={r1,r2,-,rn}是要进行排列的n个元素,Ri=R-{ri}.集合X中元素的全排列记为perm(X).(ri)perm(X)表示在全排列perm(X)的每一个排列前加上前缀得到的排列.R的全排列可归纳定义如下: 当n=1时,perm(R)=(r),其中r是集合R中唯一的元素:当n>1时,perm(R)由(r1)perm(R1),(r2)perm(R2),-,(rn)perm(Rn)构成.实现思想:将

[BZOJ1072][SCOI2007]排列perm 状压dp

1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 2488  Solved: 1546[Submit][Status][Discuss] Description 给一个数字串s和正整数d, 统计s有多少种不同的排列能被d整除(可以有前导0).例如123434有90种排列能被2整除,其中末位为2的有30种,末位为4的有60种. Input 输入第一行是一个整数T,表示测试数据的个数,以下每行一组s和d,中间

stoi2014 perm

开始补状压DP 1 #include<cstdio> 2 #include<cstring> 3 #include<iostream> 4 #include<algorithm> 5 #include<queue> 6 #define inc(i,l,r) for(int i=l;i<=r;i++) 7 #define dec(i,l,r) for(int i=l;i>=r;i--) 8 #define link(x) for(edg

BZOJ 2111 Perm 排列计数(满二叉树)

题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=2111 题意:求1到n有多少种排列满足:A[i]>A[i/2](2<=i<=n). 思路:形式类似二叉树.建模之后其实就是n个节点的不同的满二叉树有多少种?用f[i]表示i个节点的满二叉树个数,则f[n]=f[L]*f[R]*C(n-1,L).其中L和R对于确定的n来说是确定的.比如n=10时,左右子树分别有6.3个点. i64 a[N],n,p,f[N]; void init(

bzoj1072【SCOI2007】排列perm

1072: [SCOI2007]排列perm Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 1479  Solved: 928 [id=1072" style="color:blue; text-decoration:none">Submit][Status][id=1072" style="color:blue; text-decoration:none">Discuss] Des

Tomcat 6.x Perm区内存泄露问题

Tomcat 6.x JSP文件最后改动时间大于当前系统时间导致Perm区内存泄露问题(java Memory pool CMS Perm Gen) 出现场景: 因为測试业务,须要模拟跨天測试,所以一般会採用改动server实现.来完毕測试业务,測试完毕后,不会马上同步系统时间.而直接公布上线,这时问题就出现了,因为使用穿越时间打包的,所以打包的全部文件最后改动时间都穿越了. 比如:今天是:2015.1.1  为了完毕測试,把系统时间穿越到 2015.1.5.  这个时候打包的全部文件最后改动时

洞悉find中的德摩根定律和条件权限perm

1.德摩根定律 (1)初悉德摩根定律儿 在命题逻辑和逻辑代数中,德·摩根定律(或称德·摩根定理)是关于命题逻辑规律的一对法则. 奥古斯塔斯·德·摩根首先发现了在命题逻辑中存在着下面这些关系: 非(A 且 B) = (非 A) 或 (非 B)非(A 或 B) = (非 A) 且 (非 B) (2)图解德摩根定律 1>.非(A or B) = (非 A) and (非 B) 约定以下图中矩形代表全部,圆A和圆B是矩形的一部分并有部分相交 1)A or B,如下图中的黑色部分:     属于A或者是属

Subject:“find -perm”

1 find . -perm 664 2 3 Search for files which have read and write permission for their owner, and group, but which other users can read but not write to. 4 Files which meet these criteria but have other permissions bits set (for example if someone ca

Tomcat7 perm space解决(转)

set JAVA_OPTS=%JAVA_OPTS% -Xms256m -Xmx512m -XX:CompileThreshold=8000 -XX:PermSize=128m -XX:MaxPermSize=256m -Xverify:none -da 注意:很多说要加上参数-server,即set JAVA_OPTS=%JAVA_OPTS% -server -Xms256m -Xmx512m -XX:CompileThreshold=8000 -XX:PermSize=48m -XX:MaxP