zoukankan      html  css  js  c++  java
  • Auto X2021 K Increasing Sequence

    还是姿势水平不太行,这道题其实很简单。

    很容易发现最后的序列一定是一个上升序列,并且值域是(1-32)的,很小。

    进一步的,我们可以发现,删数可以随意删,只要我们能尽量合成较大的数就行了。

    我们可以令(f[j][i])表示从(j)开始,要合成一个(i),最近会跳到什么位置。

    这个数组显然是用来倍增的,我们枚举的时候可以从左向右枚举一下,维护出这个数组。

    对于询问,直接从右端点向前跳即可。

    #include<bits/stdc++.h>
    #define N 100009
    using namespace std;
    typedef long long ll;
    int f[N][41];
    int n,m,a[N];
    inline ll rd(){
    	ll x=0;char c=getchar();bool f=0;
    	while(!isdigit(c)){if(c=='-')f=1;c=getchar();}
    	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
    	return f?-x:x;
    }
    int main(){
        int T=rd();
    	while(T--){
    		n=rd();m=rd();
    		for(int i=0;i<=n;++i){
    			for(int j=0;j<=40;++j)f[i][j]=-1;
    		}
    		for(int i=1;i<=n;++i){
    			a[i]=rd();
    		}
    		for(int i=1;i<=40;++i){
    			int now=-1;
    			for(int j=1;j<=n;++j){
    				if(a[j]<i){
    					if(f[j][i-1]!=-1&&f[f[j][i-1]][i-1]!=-1)f[j][i]=f[f[j][i-1]][i-1];
    					else f[j][i]=now;
    				}
    				else if(a[j]==i)f[j][i]=j-1,now=j-1;
    				else now=-1;
    			}
    		}
    		while(m--){
    			int l=rd();int r=rd();
    			int ans=0;
    			for(int i=40;i>=1;--i)if(f[r][i]>=l-1){
    				ans+=i;
    				r=f[r][i];
    			}
    			printf("%d
    ",ans); 
    		}
    	} 
        return 0;
    }
    
    
  • 相关阅读:
    12-14面向对象--抽象基类、接口、委托
    关于 try catch catch
    C# using 三种使用方式
    互斥锁(Mutex)
    C#中Monitor类、Lock关键字和Mutex类
    System.Data.SQLite
    Dictionary<TKey, TValue> 类
    AttributeTargets 枚举
    C# is和as操作符
    合并委托(多路广播委托)
  • 原文地址:https://www.cnblogs.com/ZH-comld/p/15416260.html
Copyright © 2011-2022 走看看