zoukankan      html  css  js  c++  java
  • 【ybtoj】【RMQ问题】与众不同

    题意

    题解

    虽然在(RMQ)的章节里,但是这题的重点不在(RMQ),只是一个优化
    考虑如何找到一段完美序列
    记录(lst[val])表示val值上次出现的位置,(pre[i])表示以(i)为结尾的完美序列的起点
    那么转移式很显然,(pre[i]=max(lst[a[i]]+1,pre[i-1]))
    对于一段询问的区间,考虑如何求完美序列的长度
    对于区间内每一个点(i),(pre[i])可能在区间外((l)左边),也可能在区间内((l)右边)

    • 如果(pre[i]<l),那么以(i)结尾的完美序列长度就是(i-l+1)
    • 如果(pre[i]>=l),那么以(i)为结尾的完美序列长度就是(i-pre[i]+1)
      因此可以二分找到一个分界点(now),(now)左边的完美序列最大值为(now-l+1),右边的则为区间内(i-pre[i]+1),记为(f[i]),可以用ST表维护静态区间最大值
      二分的时候注意特判边界情况!

    代码

    #include<bits/stdc++.h>
    using namespace std;
    #define ll long long
    const int INF = 0x3f3f3f3f,N = 2e6+10;
    inline ll read()
    {
    	ll ret=0;char ch=' ',c=getchar();
    	while(!(c>='0'&&c<='9')) ch=c,c=getchar();
    	while(c>='0'&&c<='9') ret=(ret<<1)+(ret<<3)+c-'0',c=getchar();
    	return ch=='-'?-ret:ret;
    }
    map<int,int> lst;
    int n,m,a[N],dp[N][22],Log[N],pre[N],f[N];
    void buildst()
    {
    	for(int j=1;(1<<j)<=n;j++)
    		for(int i=1;i+(1<<j)-1<=n;i++)
    			dp[i][j]=max(dp[i][j-1],dp[i+(1<<(j-1))][j-1]);
    	int k=0;
    	for(int i=1;i<=n;i++)	
    	{
    		if((1<<k)<=i) k++;
    		Log[i]=k-1;
    	}
    }
    inline int query(int l,int r)
    {
    	int k=Log[r-l+1];
    	return max(dp[l][k],dp[r-(1<<k)+1][k]);
    }
    inline int find(int l,int r)
    {
    	int L=l;
    	while(l<r)
    	{
    	//printf("find(%d,%d)
    ",l,r);
    		int mid=(l+r)>>1;
    		if(pre[mid]<L) l=mid+1;
    		else r=mid;
    	}
    	return l;
    }
    int main()
    {
    	n=read(),m=read();
    	for(int i=1;i<=n;i++) 
    	{
    		a[i]=read();
    		pre[i]=max(pre[i-1],lst[a[i]]+1); 
    		lst[a[i]]=i;
    		f[i]=i-pre[i]+1;
    		dp[i][0]=f[i];
    		//printf("pre[%d]=%d
    ",i,pre[i]);
    	}
    	//for(int i = 1 ; i <= n ; i ++)	printf("pre[%d]=%d , f = %d
    ",i,pre[i],f[i]);
    	buildst();
    	
    	for(int i=1;i<=m;i++)
    	{
    		int l=read(),r=read();
    		l++,r++;
    		int now=find(l,r);	
    		int ans=(now-1)-l+(1);
    		if(pre[r]<=l) {printf("%d
    ",r-l+1);continue;}
    		//printf("now=%d,ans = %d
    ",now,ans);
    		if(now<=r) 
    			if(pre[now]>=l)ans=max(ans,query(now,r));
    		//printf(" query (%d,%d) = %d
    ",now,r,query(now,r));
    		printf("%d
    ",ans);
    	}
    	/*
    	while(m--)
    	{
    		int l = read()+1 , r = read()+1;
    		int now = lower_bound(pre+l+1,pre+r+1,l)-pre-1;
    		int ans = now - l + 1;
    		if(now < r) ans = max(ans,query(now+1,r));
    //		printf("(%d,%d)
    ",l,r);
    //		printf("now = %d
    ",now); 
    		printf("%d
    ",ans);
    	}
    	*/ 
    	return 0;
    }
    /*
    12 3
    2 5 4 1 2 3 6 2 4 3 1 0
    0 8
    2 6
    5 11
    */
    
  • 相关阅读:
    [eslintpluginvue] [vue/nounusedvars] 'scope' is defined but never used.
    Vue项目中添加锁屏功能
    前端文档汇总(含代码规范、开发流程、知识分享,持续更新)
    vscode格式化Vue出现的问题
    下盘不稳 被忽视的项目风险
    项目沟通中的一点经验心得
    如何才能更合理地分配项目奖金?
    关于企业的薪酬体系之思考
    导致项目失败的两大隐形杀手
    如何让项目总结会议更有效果?
  • 原文地址:https://www.cnblogs.com/conprour/p/15255571.html
Copyright © 2011-2022 走看看