• 优美序列(sequence)


    问题描述

    Lxy养了N头奶牛,他把N头奶牛用1..N编号,第i头奶牛编号为i。为了让奶牛多产奶,每天早上他都会让奶牛们排成一排做早操。奶牛们是随机排列的。在奶牛排列中,如果一段区间[L,R]中的数从小到大排列后是连续的,他认为这段区间是优美的。比如奶牛排列为:(3, 1, 7, 5, 6, 4, 2),区间[3,6]是优美的,它包含4,5,6,7连续的四个数,而区间[1,3] 是不优美的。Lxy的问题是:对于给定的一个区间[L,R](1<=L<=R<=N), 他想知道,包含区间[L,R]的最短优美区间,比如区间[1,3]的最短优美区间是[1,7]。

    输入

    第一行为一个整数N,表示奶牛的个数。
    第二行为1到N的一个排列,表示奶牛的队伍。
    第三行为一个整数M,表示有M个询问。
    后面有M行,每行有两个整数L,R表示询问区间。

    输出

    输出为M行,每行两个整数,表示包含询问区间的最短优美区间。

    输入输出样例

    样例1

    input
    7
    3 1 7 5 6 4 2
    3
    3 6
    7 7
    1 3
    output
    3 6
    7 7
    1 7

    样例2

    input
    10
    2 1 4 3 5 6 7 10 8 9
    5
    2 3
    3 7
    4 7
    4 8
    7 8
    output
    1 4
    3 7
    3 7
    3 10
    7 10

    数据范围

    15%的数据满足: 1 <=N,M <= 15;
    50%的数据满足:1 <=N,M <= 1000。
    100%的数据满足:1 <=N,M <= 100000。

    解析

    为了给出题人留面子,不让他被骂出个题只有一种解法而且只有满分解法,我先给个80分做法。
    预处理一个数组pos[i],表示数i在原数组的位置(第几个数)。
    在询问区间内找一个最小值和最大值,作为新的l和r,新的l和r作为一个询问区间,在pos数组里找一个最小值和最大值,他们再作为新的l和r,形成询问区间,在原数组寻找最小值和最大值,并再次重复刚才的操作……
    上述过程可能很无脑很中二,然而这就是模拟题意找出答案的过程。
    最大值最小值用st表预处理,一共四个st表,比线段树好写……
    那么……
    正解是分治,像归并排序那样。
    不断求[l,mid] [mid+1,r]的优美序列,直到分成[mid,mid+1]
    可以证明是正确的。
    事实上分治做的熟练的人可能一眼秒这道题。

    代码

    80pts

    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    template<class T>
    void read(T &res)
    {
    	res = 0;
    	T f = 1;
    	char cc = getchar();
    	while(cc < '0' || cc > '9')
    	{
    		if(cc == '-') f = -1;
    		cc = getchar();
    	}
    	while(cc >= '0' && cc <= '9')
    	{
    		res = res * 10 + cc - '0';
    		cc = getchar();
    	}
    	res *= f;
    }
    const int maxn = 1e5 + 5;
    int n,m;
    int seqmin[maxn][50];
    int posmin[maxn][50];
    int seqmax[maxn][50];
    int posmax[maxn][50];
    int ansl,ansr;
    void init()
    {
    	for(int j=1;(1<<j) <= n;j++)
        {
            for(int i=0;i+(1<<j)-1 <= n;i++)
            {
                seqmax[i][j] = max(seqmax[i][j-1],seqmax[i+(1<<(j-1))][j-1]); // 1
                seqmin[i][j] = min(seqmin[i][j-1],seqmin[i+(1<<(j-1))][j-1]); // 2
                posmax[i][j] = max(posmax[i][j-1],posmax[i+(1<<(j-1))][j-1]); // 3
                posmin[i][j] = min(posmin[i][j-1],posmin[i+(1<<(j-1))][j-1]); // 4
            }
        }
    }
    int query(int l,int r,int ju)
    {
        int t = int(log((double)(r - l + 1)) / log(2.0));
        if(ju == 1)
        	return max(seqmax[l][t],seqmax[r-(1<<t)+1][t]);
        if(ju == 2)
        	return min(seqmin[l][t],seqmin[r-(1<<t)+1][t]);
    	if(ju == 3)
        	return max(posmax[l][t],posmax[r-(1<<t)+1][t]);
        if(ju == 4)
        	return min(posmin[l][t],posmin[r-(1<<t)+1][t]);
    }
    void change(int inl,int inr)
    {
    	int templ,tempr,endl,endr;
    	templ = query(inl,inr,2);
    	tempr = query(inl,inr,1);
    	endl = query(templ,tempr,4);
    	endr = query(templ,tempr,3);
    	if(endl == inl && endr == inr)
    	{
    		ansl = endl;
    		ansr = endr;
    		return;
    	}
    	else
    		change(endl,endr);
    	
    }
    int main()
    {
    	freopen("sequence.in","r",stdin);
    	freopen("sequence.out","w",stdout);
    	read(n);
    	for(int i=1;i<=n;i++)
    		read(seqmin[i][0]),seqmax[i][0] = seqmin[i][0];
    	for(int i=1;i<=n;i++)
    		posmax[seqmin[i][0]][0] = i,posmin[seqmin[i][0]][0] = i;
    	init();
    	read(m);
    	while(m--)
    	{
    		int l,r;
    		read(l);read(r);
    		change(l,r);
    		printf("%d %d
    ",ansl,ansr);
    	}
    	return 0;
    }
    

    100pts

    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    const int N=100005;
    #define pb push_back
    #define lc (o<<1)
    #define mid (l+r>>1)
    #define rc ((o<<1)|1)
    struct ask{
        int L,num;
        bool operator <(const ask &u)const{
            return L<u.L;
        }
    };
    vector<ask> g[N];
    multiset<ask> s;
    multiset<ask> :: iterator it;
    int n,a[N],p[N],mx[N*4],pos[N*4],Q;
    int le,ri,w,al[N],ar[N],M,P,tag[N*4];
    inline void mt(int o){
        mx[o]=max(mx[lc],mx[rc]);
        pos[o]=(mx[rc]==mx[o]?pos[rc]:pos[lc]);
    }
    inline void work(int o,int der){ tag[o]+=der,mx[o]+=der;}
    inline void pd(int o){ if(tag[o]) work(lc,tag[o]),work(rc,tag[o]),tag[o]=0;}
    void build(int o,int l,int r){
        mx[o]=r,pos[o]=r;
        if(l==r) return;
        build(lc,l,mid),build(rc,mid+1,r);
    }
    void update(int o,int l,int r){
        if(l>=le&&r<=ri){ work(o,w); return;}
        pd(o);
        if(le<=mid) update(lc,l,mid);
        if(ri>mid) update(rc,mid+1,r);
        mt(o);
    }
    void query(int o,int l,int r){
        if(l>=le&&r<=ri){ if(mx[o]>M) M=mx[o],P=pos[o]; return;}
        pd(o);
        if(ri>mid) query(rc,mid+1,r);
        if(le<=mid) query(lc,l,mid);
    }
    inline bool can(int cc){
        le=1,ri=it->L,M=P=0;
        query(1,1,n);
        if(M==cc){ al[it->num]=P,ar[it->num]=cc; return 1;}
        return 0;
    }
    inline void solve(){
        build(1,1,n),w=1;
        ask inf=(ask){233333,0};
        for(int i=1;i<=n;i++){
            for(ask x:g[i]) s.insert(x);
            ri=p[a[i]-1],le=1;
            if(ri&&ri<i) update(1,1,n);
            ri=p[a[i]+1],le=1;
            if(ri&&ri<i) update(1,1,n);
            for(;s.size();s.erase(it)){
                it=--s.lower_bound(inf);
                if(!can(i)) break;
            }
        }
    }
    int main(){
      freopen("sequence.in","r",stdin);
      freopen("sequence.out","w",stdout);
         
        scanf("%d",&n);
        for(int i=1;i<=n;i++) {
        	scanf("%d",&a[i]);
        	p[a[i]]=i;
        };
        scanf("%d",&Q);
        for(int i=1,l,r;i<=Q;i++){
            scanf("%d %d",&l,&r);
            g[r].pb((ask){l,i});
        }
        solve();
        for(int i=1;i<=Q;i++)  printf("%d %d
    ",al[i],ar[i]);
        return 0;
    }
    
    
  • 相关阅读:
    实验0 了解和熟悉操作系统
    软件工程感想
    递归下降分析法--算数语法分析
    有限自动机的构造与识别
    评论
    文法解释
    【编译CEF3】2017-07 添加支持mp3 mp4的编译日记
    Visual Studio 2015/2013安装失败:Microsoft Visual Studio 2015 Shell (Minimum) Interop Assemblies 安装时发生严重错误
    [RAD Studio 10.2 Tokyo] Error:java.lang.UnsupportedClassVersionError: com/android/dx/command/Main : Unsupported major错误解决
    Delphi 编译出来的程序被小红伞报病毒 TR/Spy.Banker.Gen4 [trojan]
  • 原文地址:https://www.cnblogs.com/Ch-someone/p/9664616.html
Copyright © 2020-2023  润新知