zoukankan      html  css  js  c++  java
  • SDUSTOJ 1796 哆啦A梦的军队(线段树维护前缀位置)

    Description

    在2050年机器人战争爆发,聪明的机器猫为了帮助大雄打赢这场战 争,从自己口袋里掏出了机器人战棋,每一个战棋都可以成为一名战士,哆啦A梦决定给他们整整队,哆啦A梦发现第 i 个位置的战士编号为 Ai(显然 A 是一个排列)。经过计算,哆啦A梦发现,让第 i 个位置的战士编号为 Bi 时,他的军队可以发挥出最大的战斗力(保证 B 也是一个排列)。
    哆啦A梦可以发出指令来改变战士们的排列顺序,每一次,他都会报出一个整数 i(1≤i<n)。如果排在第 i 个位置的战士编号大于第 i+1 个位置的战士,那么这两个战士会交换顺序,否则这一个命令将会被忽略。
    现在哆啦A梦希望他的军队能够发挥出最强大的战斗力,于是他想要知道是否存在一种指令序列,使得战士们可以按照排列 B 的方式排列。
    但是因为战士数目实在是太多,哆啦A梦一时间也没有看出答案。于是他用时间机器带来了你——21世纪最著名的民间科学家来帮他计算这个问题的答案。

    Input

    输入数据第一行包含一个正整数 n(n<=100000)。

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

    Output

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

    Sample Input

    3
    2 3 1
    2 1 3
    3
    2 1 3
    3 1 2

    Sample Output

    YES
    NO

    思路:这道题是山科第三届校赛的H题,我们队过的最后一道题,由于太弱,想了大概一个小时左右才初步有了思路
    就是先建一棵max的线段树,数组a和b分别记录交换之前和交换之后数值的下标
    然后从大到小循环,每次判断该数值是否向右移动(或者不移动),如果成立就询问线段树初始位置在该元素右边的
    值移动后所在的最左端的位置。当前数值移动后的位置必须小于查询的结果。
    然后每个值都更新线段树,将初始位置的值更新为交换之后的位置。
    然后同理从小到大循环,每次判断向左移动,询问最右端的位置就好了
    /* ***********************************************
    Author        :devil
    Created Time  :2016/4/26 13:11:52
    ************************************************ */
    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <algorithm>
    #include <vector>
    #include <queue>
    #include <set>
    #include <map>
    #include <string>
    #include <cmath>
    #include <stdlib.h>
    using namespace std;
    const int N=100005;
    int n,a[N],b[N],tree[N<<2];
    void build1(int node,int l,int r)
    {
        if(l==r)
        {
            tree[node]=N;
            return ;
        }
        int m=(l+r)>>1;
        build1(node<<1,l,m);
        build1(node<<1|1,m+1,r);
        tree[node]=min(tree[node<<1],tree[node<<1|1]);
    }
    void update1(int node,int l,int r,int p)
    {
        if(l==r)
        {
            tree[node]=b[p];
            return ;
        }
        int m=(l+r)>>1;
        if(a[p]<=m) update1(node<<1,l,m,p);
        else update1(node<<1|1,m+1,r,p);
        tree[node]=min(tree[node<<1],tree[node<<1|1]);
    }
    int query1(int node,int l,int r,int p)
    {
        if(l>=p) return tree[node];
        int m=(l+r)>>1,ans;
        ans=query1(node<<1|1,m+1,r,p);
        if(p<=m) ans=min(ans,query1(node<<1,l,m,p));
        return ans;
    }
    void build2(int node,int l,int r)
    {
        if(l==r)
        {
            tree[node]=0;
            return ;
        }
        int m=(l+r)>>1;
        build2(node<<1,l,m);
        build2(node<<1|1,m+1,r);
        tree[node]=max(tree[node<<1],tree[node<<1|1]);
    }
    void update2(int node,int l,int r,int p)
    {
        if(l==r)
        {
            tree[node]=b[p];
            return ;
        }
        int m=(l+r)>>1;
        if(a[p]<=m) update2(node<<1,l,m,p);
        else update2(node<<1|1,m+1,r,p);
        tree[node]=max(tree[node<<1],tree[node<<1|1]);
    }
    int query2(int node,int l,int r,int p)
    {
        if(r<=p) return tree[node];
        int m=(l+r)>>1,ans;
        ans=query2(node<<1,l,m,p);
        if(p>m) ans=max(ans,query2(node<<1|1,m+1,r,p));
        return ans;
    }
    int main()
    {
        //freopen("in.txt","r",stdin);
        while(~scanf("%d",&n))
        {
            int x,flag=1;
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&x);
                a[x]=i;
            }
            for(int i=1; i<=n; i++)
            {
                scanf("%d",&x);
                b[x]=i;
            }
            build1(1,1,n);
            for(int i=n; i>0; i--)
            {
                if(a[i]<=b[i]&&b[i]>query1(1,1,n,a[i]))
                {
                    flag=0;
                    break;
                }
                update1(1,1,n,i);
            }
            if(!flag)
            {
                printf("NO
    ");
                continue;
            }
            build2(1,1,n);
            for(int i=1; i<=n; i++)
            {
                if(a[i]>=b[i]&&b[i]<query2(1,1,n,a[i]))
                {
                    flag=0;
                    break;
                }
                update2(1,1,n,i);
            }
            if(!flag) printf("NO
    ");
            else printf("YES
    ");
        }
        return 0;
    }
  • 相关阅读:
    C++ const
    facebook hacker cup 2013资格赛第二题
    最大全1子矩阵
    java HashMap的keyset方法
    树状数组
    Java entry
    一个数学证明:1(1x1)(1x2)...(1xn)<=x1+x2+...+xn, xi在[0,1]
    传教士野蛮人过河问题python
    在cmd中为命令设置别名以及启动cmd时自动执行bat
    合取Λ,析取V,容易记混吗?
  • 原文地址:https://www.cnblogs.com/d-e-v-i-l/p/5434713.html
Copyright © 2011-2022 走看看