摘希


私信TA

用户名:dotcpp0725198

访问量:962

签 名:

等  级
排  名 16324
经  验 807
参赛次数 0
文章发表 1
年  龄 0
在职情况 学生
学  校 东北林业大学
专  业 计算机科学与技术

  自我简介:

解题思路:关于此题,没来没当回事,所以使用了比较暴力的做法。然后经历了空间超限、时间超限等问题,下面是三种解法。

注意事项:

参考代码:

/*第一份代码,此份代码思维简单粗暴,但空间超限仅为只过了两份数据,但时间消耗小*/
#include<iostream>
#include<vector>


using namespace std;


const int MAX = 100001;//数据量最大为100000。

/*
第一次想法:
简单粗暴,把所有的n个整数两两异或的结果存放到一个n*n的矩阵中
然后在后续的输入中直接查询矩阵就好
这就像是对数据进行分析,将分析后的数据存放,使用的时候在读取
*/

int main()
{

    int n, m, x;
    cin >> n >> m >> x;
    vector<int> a(n);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
    vector<int> l(m);
    vector<int> r(m);
    for (int i = 0; i < m; i++)
    {
        cin >> l[i]>>r[i];
    }
    
    //定义n*n的结果矩阵,存放结果。
    vector<vector<bool>> res(n, vector<bool>(n,false));
    
    //矩阵赋值过程
    //a1要与a2,a3,a4...进行异或
    //a2要与a3,a4,a5...进行异或
    for (int i = 0; i < n; i++)
    {
        for (int j = i+1; j < n; j++)
        {
            if ((a[i] ^ a[j]) == x)
            {
                res[i][j] = true;
            }
        }
    }

    //然后是根据该数据集处理问题
    
    for (int i = 0; i < m; i++)
    {
        //对于每一组数据
        
        bool exit = false;

        //需要检查|l[i]到r[i],l[i]到r[i]|这个矩阵中有没有1。

        for (int j = l[i] - 1; j <= r[i] - 1; j++)
        {
            for (int k = j+1; k <= r[i] - 1; k++)
            {
                if (res[j][k]==true)
                {
                    exit = true;
                    break;
                }
            }
            if (exit)
                break;
        }
        cout << (exit ? "yes" : "no") << endl;;
    }

    return 0;
}
/*代码注释详细,我就不多比比了,接下请看第二份代码,使用了dp,但也没有满分,因为时间超限卡了四份数据*/
#include<iostream>
#include<vector>


using namespace std;


const int MAX = 100001;//数据量最大为100000。



int main()
{
    /*
    第一种方法很明显十分笨拙,为什么呢?
    处理了没必要的数据,我们不必知道那么详细的数据,存放起来
    数据处理的过于详细不仅会导致占用空间,而且在使用数据时还要对数据进行在此处理
    我们只需要从数据中处理出我们需要的信息,不必那么详细,在使用时能刚好就拿来用。
    那么这么想,
    对每一个a[i],创建对应的一个整形变量,存放着到那个位置有异或为1。该变量初始化为无限大,然后在输入数据的同时不断更新。
    */

    int n, m, x;
    cin >> n >> m >> x;
    vector<int> a(n);
    vector<int> res_a(n,MAX);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
        //每输入一个数,都要对已输入的数的res_a进行动态的检测修改。
        for (int j = 0; j < i; j++)
        {
            //倘若这个值的所在更小,那么才有检测的必要
            if (i < res_a[j])
            {
                if ((a[j] ^ a[i]) == x)
                {
                    //更新
                    res_a[j] = i;
                }
            }
        }
    }
    //此时的res_a里,有每个位置的值自己异或结果为x的最小位置。
    //我们想要的,是每个位置异或为x的最小区间。因此我们最后要更新一下这个结果。

    for (int i = n - 2; i >= 0; i--)
    {
        if (res_a[i] > res_a[i+1])
            res_a[i] = res_a[i + 1];
    }

    vector<int> l(m);
    vector<int> r(m);
    for (int i = 0; i < m; i++)
    {
        cin >> l[i] >> r[i];
    }


    for (int i = 0; i < m; i++)
    {
        if (res_a[l[i] - 1] <= r[i] - 1)
            cout << "yes" <<endl;
        else
            cout << "no" <<endl;
    }
    return 0;
}
/*这个算法的时间复杂度为O(n²),因此卡了一部分数据。*/


/*注释详细,我就不多比比了,下面看第三份满分代码*/
#include<iostream>
#include<vector>


using namespace std;


int main()
{
    ios_base::sync_with_stdio(0);
    cin.tie(0);

    int n, m, x;
    cin >> n >> m >> x;
    vector<int> a(n);

    //定义dp,其中存放对于每个位置i来说,若i为r,那么期间存在与l异或为x的最小的区间,即最大的l。
    //初始化时,要让区间尽量大,于是让l尽量小,我干脆让其为-1
    vector<int> dp(n, -1);

    //存放每一个a[i]的位置,a[i]的最大为2的20次方,约小于1 100 000
    //且初始化值为最小
    vector<int> position_of_a(1100000,-1);
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }

    //i从1开始是因为,第一个的索引为0的数作为r的话,一定不存在yes的情况
    //而且,for循环里有需要i-1的地方。
    for (int i = 1; i < n; i++)
    {
        position_of_a[a[i]] = i;
        //但是,如果数据中有重复的数据怎么办呢?
        //我想,对于每一个a[i],它与x异或,得到目标值。
        //我们令a[i]的位置为r,那么目标值的位置一定是在a[i]的左边的。
        //那么对于目标值,如果已输入的目标值有多个,那么我一定希望取不大于a[i]中尽量大的,以获得更小的区间。
        //而这时,a[i]右边的值的位置信息,我们还没有赋值,被初始化为最小整形,那么我直接取目标位置最大的就好。
        //那么,dp里就是这个position_of_a[[i]^x],或者是左边的那个值的可异或区间
        dp[i] = max(position_of_a[a[i] ^ x],dp[i-1]);
    }
    /*检验*/
    /*
    for (int i = 0; i < n; i++)
    {
        cout << dp[i] << endl;
    }
    */
    vector<int> l(m);
    vector<int> r(m);
    for (int i = 0; i < m; i++)
    {
        cin >> l[i] >> r[i];
    }
    for (int i = 0; i < m; i++)
    {
        if (dp[r[i] - 1] >= l[i] - 1)
            cout << "yes"<<'\n';
        else
            cout << "no" << '\n';
    }
    
    return 0;
}
/*这里要注意“
ios_base::sync_with_stdio(0);
    cin.tie(0);
”是必要的。或者把输入输出改为scanf,printf,这样不需要这两行也能过。还有在使用这两行代码时不能使用endl换行,而要使用'\n'。
总之,干脆使用scanf,printf吧,输出格式化也方便。*/


 

0.0分

7 人评分

  评论区

  • «
  • »