zoukankan      html  css  js  c++  java
  • 【uoj#180】[UR #12]实验室外的攻防战 结论题+树状数组

    题目描述

    给出两个长度为 $n$ 的排列 $A$ 和 $B$ ,如果 $A_i>A_{i+1}$ 则可以交换 $A_i$ 和 $A_{i+1}$ 。问是否能将 $A$ 交换成 $B$ 。

    输入

    输入数据第一行包含一个正整数 $n$ 。

    接下来两行每行 $n$ 个正整数,分别描述排列 $A$ 和排列 $B$ 。

    输出

    对于每组数据,如果存在这样的指令序列,输出“YES”,否则输出“NO”(引号不输出,请注意大小写)。

    样例输入

    5
    4 1 2 5 3
    1 2 4 3 5

    样例输出

    YES


    题解

    结论题+树状数组

    结论:能将 $A$ 交换成 $B$ 的充要条件为:不存在 $i<j$ 使得 $A_i<A_j$ 且 $B_i>B_j$ 。

    证明:简单模拟冒泡排序的过程即可得出结论。

    那么我们要判断的就是是否存在 $i<j$ 使得 $A_i<A_j$ 且 $B_i>B_j$。

    这看起来是一个三维偏序问题,但实际上我们只需要判断其存在性。因此可以:扫描法处理 $i<j$ ,对于从小到大的每个 $j$ ,找出所有 $A_i<A_j$ 中 $B_i$ 的最大值,看最大值是否大于 $B_j$,然后再加入 $j$ 。

    这样就可以仅使用树状数组解决问题,时间复杂度 $O(nlog n)$

    #include <cstdio>
    #include <algorithm>
    #define N 100010
    using namespace std;
    int n , a[N] , b[N] , f[N];
    inline void add(int x , int a)
    {
    	int i;
    	for(i = x ; i <= n ; i += i & -i)
    		f[i] = max(f[i] , a);
    }
    inline int query(int x)
    {
    	int i , ans = 0;
    	for(i = x ; i ; i -= i & -i)
    		ans = max(ans , f[i]);
    	return ans;
    }
    int main()
    {
    	int i , x;
    	scanf("%d" , &n);
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , a[x] = i;
    	for(i = 1 ; i <= n ; i ++ ) scanf("%d" , &x) , b[x] = i;
    	for(i = 1 ; i <= n ; i ++ )
    	{
    		if(query(a[i]) > b[i])
    		{
    			puts("NO");
    			return 0;
    		}
    		add(a[i] , b[i]);
    	}
    	puts("YES");
    	return 0;
    }
    
  • 相关阅读:
    关于python3.x语法
    linux简单的安全防护
    hydra(爆破神器)
    扫描Linux服务器查找恶意软件和rootkit的一款工具
    chm 已取消到该网页的导航,打不开!
    android:activity知识点
    C# Mutex对象的使用
    惯性质量与引力质量的联系
    c# timer使用
    weiFenLuo.winFormsUI.Docking.dll学习
  • 原文地址:https://www.cnblogs.com/GXZlegend/p/8244100.html
Copyright © 2011-2022 走看看