• NOI模拟(3.3)螺旋序列(出题人一定是月厨)


    Description

    S也想寻求真正的智慧,然而由于“抑制力”的存在,她必须先解决一系列询
    问。
    有一个长度为n的序列a,一个长度为m序列b被称为螺旋序列当且仅当
    b1=bm且对于1<=i<=m有bi<=b1。
    S需要回答q个询问,每个询问用l,r两个参数描述,表示询问区间[l,r]的最长
    连续子螺旋序列的长度。

    Input

    第一行两个整数n,q,表示序列长度和询问数。
    第二行n个整数ai表示序列a。
    以下q行,每行两个整数l,r表示一次询问。

    Output

    对每次询问输出一行一个整数表示最大连续螺旋序列的长度。

    Sample Input

    5 3
    3 2 1 2 3
    1 4
    2 5
    1 5

    Sample Output

    3
    3
    5

    Data Constraint

    本题采用捆绑测试,只有通过一个子任务的全部数据才能得到该子任务分
    数,否则不得分。
    子任务1(20分):n,m<=10
    子任务2(20分):n,m<=1000
    子任务3(20分):n,m<=2*10^5,1<=ai<=10
    子任务4(40分):n,m<=5*10^5;|ai|<=10^9

    Solution

    30分的裸暴力

    离散化相等的数字,做一个链表,st表处理区间最大值,对每个询问都暴力去跳

    #include <map>
    #include <vector>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #define rg register
    
    template<class T> inline T dma(rg T x,rg T y) {return x>y?x:y;}
    template<class T> inline void read(rg T &x)
    	{
    	rg int c=getchar();rg bool b=0;
    	for(;c<48||c>57;c=getchar())
    		if(c==45)b=1;
    	for(x=0;c>47&&c<58;c=getchar())
    		x=(x<<1)+(x<<3)+c-48;
    	if(b)x=-x;
    	}
    
    const int N=500010;
    std::vector<int>vc;
    std::map<int,int>hc;
    int n,q,seq[N],fir[N],nex[N],st[20][N],bin[20],lgg[20],ans;
    
    void sequence_table()
    	{
    	lgg[0]=-1;for(rg int i=1;i<=n;i++)lgg[i]=lgg[i>>1]+1;
    	for(rg int i=0;i<20;i++)bin[i]=1<<i;
    	for(rg int i=1;i<=n;i++)st[0][i]=seq[i];
    	for(rg int t=1;t<20;t++)
    		for(rg int i=1;i<=n;i++)
    			if(i+bin[t]-1<=n)st[t][i]=dma(st[t-1][i],st[t-1][i+bin[t-1]]);
    	}
    
    int sequence_query(rg int x,rg int y)
    	{
    	rg int t=lgg[y-x+1];
    	return dma(st[t][x],st[t][y-bin[t]+1]);
    	}
    
    void jump(rg int x,rg int lim)
    	{
    	for(rg int rig=x,lef=nex[x];lef>=lim;lef=nex[lef])
    		{
    		while(rig>lef&&sequence_query(lef,rig)>seq[lef])rig=nex[rig];
    		ans=dma(ans,rig-lef+1);
    		}
    	}
    
    int main()
    	{
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	read(n),read(q);
    	for(rg int i=1;i<=n;i++)
    		{
    		read(seq[i]);
    		vc.push_back(seq[i]);
    		}
    	std::sort(vc.begin(),vc.end());
    	vc.erase(std::unique(vc.begin(),vc.end()),vc.end());
    	for(rg int i=0;i<vc.size();i++)
    		hc[vc[i]]=i+1;
    	for(rg int i=1;i<=n;i++)seq[i]=hc[seq[i]];
    	memset(fir,-1,sizeof fir);
    	for(rg int i=1;i<=n;i++)
    		{
    		nex[i]=fir[seq[i]];
    		fir[seq[i]]=i;
    		}
    	sequence_table();
    	for(rg int x,y;q;q--)
    		{
    		ans=1;
    		read(x),read(y);
    		for(rg int i=y;i>=x;i--)
    			jump(i,x);
    		printf("%d
    ",ans);
    		}
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    	}
    

    出题人一定是月厨,有爱~

    考虑将这些进行jump的操作序列转化成链,离线后,用链来更新询问

    对于所有链长度小于s的,用树状数组区间最值+扫描线做

    对于所有链长度大于s的,这样的链只有n/s条,对每条链的下标预处理每个下标i所在链上的位置,对每个询问算出最优值并更新,复杂度为n*n/s

    取s=sqrt(n/logn),可以得到O(n*sqrt(n*logn))的复杂度

    #include <map>
    #include <vector>
    #include <math.h>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    
    template<class T> T mex(T x,T y) {return x>y?x:y;}
    template<class T> void read(T &x)
    	{
    	int c=getchar();bool b=0;
    	for(;c<48||c>57;c=getchar())if(c==45)b=1;
    	for(x=0;c>47&&c<58;c=getchar())x=(x<<1)+(x<<3)+c-48;
    	if(b)x=-x;
    	}
    
    const int maxn=500010;
    bool vis[maxn];
    int n,m,lim,A[maxn],st[20][maxn],lgg[maxn],L[maxn],R[maxn],ans[maxn],nex[maxn],big[maxn],cur[maxn],tr[maxn];
    
    std::map<int,int> pool;
    std::vector<int> seq;
    std::vector<std::pair<int,int> > Q[maxn];
    
    inline void Add(int x,int c)
    	{
    	for(;x<=n;x+=x&-x)tr[x]=mex(tr[x],c);
    	}
    
    inline int Get(int x)
    	{
    	int ret=0;
    	for(;x;x-=x&-x)ret=mex(ret,tr[x]);
    	return ret;
    	}
    
    inline int maxi(int x,int y)
    	{
    	int t=lgg[++y-x];
    	return mex(st[t][x],st[t][y-(1<<t)]);
    	}
    
    int main()
    	{
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	read(n),read(m);
    	lgg[0]=-1;for(int i=1;i<=n;i++)
    		{
    		read(A[i]);
    		st[0][i]=A[i];
    		lgg[i]=lgg[i>>1]+1;
    		}
    	for(int i=1;i<=m;i++)
    		{
    		read(L[i]),read(R[i]);
    		Q[L[i]].push_back(std::make_pair(R[i],i));
    		ans[i]=1;
    		}
    	for(int t=1;t<20;t++)
    		for(int i=1;i+(1<<t)-1<=n;i++)
    			st[t][i]=mex(st[t-1][i],st[t-1][i+(1<<t-1)]);
    	for(int i=n,j;i;i--)
    		{
    		if(pool.count(A[i]))
    			{
    			j=pool[A[i]];
    			if(maxi(i,j)<=A[i])nex[i]=j;
    			}
    		pool[A[i]]=i;
    		}
    	lim=static_cast<int>(sqrt(n/log(n)/log(2)));
    	for(int i=1;i<=n;i++)
    		if(!vis[i])
    			{
    			seq.clear();
    			seq.push_back(0);
    			for(int j=i;j;j=nex[j])
    				{
    				seq.push_back(j);
    				vis[j]=true;
    				}
    			if(seq.size()>=lim)
    				{
    				for(int j=1,k=0;j<=n;j++)
    					{
    					for(;k<seq.size()&&j>=seq[k];k++)big[seq[k]]=1;
    					cur[j]=k-1;
    					}
    				for(int j=1,x,y;j<=m;j++)
    					if(cur[L[j]-1]+1<seq.size())
    						{
    						x=seq[cur[L[j]-1]+1];
    						y=seq[cur[R[j]]];
    						ans[j]=mex(ans[j],y-x+1);
    						}
    				}
    			}
    	for(int i=n;i;i--)
    		{
    		if(!big[i])
    			for(int j=i;j;j=nex[j])
    				Add(j,j-i+1);
    		for(int j=0;j<Q[i].size();j++)
    			ans[Q[i][j].second]=mex(ans[Q[i][j].second],Get(Q[i][j].first));
    		}
    	for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    	}
    

      

  • 相关阅读:
    【STM32 .NET MF开发板学习29】摄像头蓝牙图像远程获取
    【.Net MF网络开发板研究04】Socket编程之服务端
    【.Net MF网络开发板研究01】IP地址设定及简单web演示
    【.Net MF网络开发板研究02】Http Server功能演示
    用VB.net开发.NET Micro Framework
    【.Net MF网络开发板研究03】获取雅虎天气(HttpClient示例)
    js中URL编码参数(UrlEncode,UrlDecode)[ansi编码] PHP好使 简单
    PHP通过SMTP实现发送邮件_包括附件 简单
    mysql case then使用 简单
    PHP中$_SERVER的详细参数与说明 简单
  • 原文地址:https://www.cnblogs.com/keshuqi/p/6506126.html
Copyright © 2020-2023  润新知