题解 | #小红的闭合标签#

小红的闭合标签

https://ac.nowcoder.com/acm/contest/128678/A

小红的闭合标签

一种方法是去掉字符串两边的<> , 在输出的时候加上即可 代码:

void work()
{
    int n ; cin >> n ;
    string s ; cin >> s ; 
    s = s.substr(1 , n - 2);
    cout << "</" << s << ">" << endl ;  
}

小红的众数

要想让x成为众数,只需要让x的出现次数达到最大即可 代码:

void work()
{
    int n , x ; cin >> n >> x ;
    unordered_map<int , int>mp ; 
    int mx = 0 ; 
    for(int i = 1 ; i <= n ; i++)
    {
        int u ; cin >> u ; 
        mp[u]++ ;
        mx = max(mx , mp[u]) ;
    }
    if(mp[x] == mx)
    {
        cout << 0 << endl ; 
    }
    else
    {
        cout << mx - mp[x] << endl ; 
    }
}

小红的数字查找

由于l和r的数据范围已经超出暴力的范围,所以我们尝试取巧的方法,观察到如果想让x * y是一个完全平方数的话,y应该是一个k * n^2的形式,其中k是x中出现次数为奇数的质因数的个数,由此对l和r进行优化,查找有没有中间值即可。需要注意的是,这里我们尽量舍弃哈希表出现次数计数 代码:

void work()
{
    int x , l , r ; cin >> x >> l >> r ;
        int kj = 1 ; 
    for(int i = 2 ; i * i <= (x) ; i++)
    {
        int count = 0 ; 
        while(x % i == 0)
        {
            count++ ;
            x /= i ; 
        }
        if(count & 1)
        {
            kj *= i ;
        }
        if(x == 1)
        {
            break ; 
        }
    }
    if(x != 1)
    {
        kj *= x ; 
    }
    
    if(l <= kj && kj <= r)
    {
        cout << kj << endl ; 
        return ; 
    }
    int a1 = sqrt(l / kj) ; 
    int a2 = sqrt(r / kj) ; 
    if(a2 - a1 != 0)
    {
        cout << (a1 + 1) * (a1 + 1) * kj << endl ; 
        return ; 
    }
    cout << -1 << endl ; 
}

小红的异或分组

从大局着眼,如果三个区间的异或和相等,那么整个数组的异或值应该是S ^ S ^ S = S , 所以我们在读取数据的时候顺便计算出异或和是多少,这里分两种情况讨论

1、如果S == 0 ,那么我们应该寻找前缀为0的位置,最后利用组合数从中选取两个分段点即可

2、如果S != 0 , 那么为了优化时间复杂度,我们考虑到前两个区间的异或前缀应该为0,而第一个区间的异或前缀为S ,所以我们统计异或前缀为S的数量,在遇到0的时候加上前面找到的即可 需要注意的是:前缀只能进行到n的前一位,因为题目要求每个区间内必须有数 代码:

void work()
{
    int n ; cin >> n ;
    vi a(n) ;
    int ans = 0 ; 
    for(int i = 0 ; i < n ; i++)
    {
        cin >> a[i] ;
        ans ^= a[i] ;
    }
    int res = 0 ; 
    if(ans != 0)
    {
        int count = 0 ; 
        int cur = 0 ;
        for(int i = 0 ; i < n - 1 ; i++)
        {
            cur ^= a[i] ;
            if(cur == ans)
            {
                count++ ;
            }
            else if(cur == 0)
            {
                res += count ; 
            }
        }
        cout << res << endl ; 
    }
    else
    {
        int count = 0 ; 
        int cur = 0 ; 
        for(int i = 0 ; i < n - 1 ; i++)
        {
            cur ^= a[i] ; 
            if(cur == 0)
            {
                count++ ;
            }
        }
        cout << count * (count - 1) / 2 << endl ; 
    }
}

小红的路径

首先我们来讨论一下不可能的情况,首先了解到如果我们想要走完所有的格子,我们必须走2*n - 1步,这必定是一个奇数,而后我们发现如果把整个矩阵看作一个棋盘的话,走奇数步(x + y)% 2的值是相反的,所以知道起点和终点的(x + y) % 2一定是不同的。

此外,我们注意一种特殊情况,也就是x1 == x2的情况,这种情况下如果x1不是1或者n,那我们是不可能构造出来的,通过第一种判断方法并不能排除他

下面开始构造

第一种情况:x1 == x2的时候,如果满足构造条件,只需要三段构造即可

第二种情况:为了减少计算量,我们可以把终点放在起点右边,打一个标记,最后反转字符串并转变方向就可以了。

我们进行三类构造,第一类是从起点到他的左边界,绕回来后到和起点x相同的位置,第二类是然后从起点到终点的部分进行蛇形构造,去到和终点x相同的位置,第三类是从终点到他的右边界,绕回来之后回到终点

至此路径构造完毕,根据情况判断是否反转即可 代码:

void work()
{
    int n, x1, y1, x2, y2;
    cin >> n >> y1 >> x1 >> y2 >> x2 ;
    if ((x1 + y1) % 2 == (x2 + y2) % 2)
    {
        cout << -1 << endl;
        return;
    }
    if (x1 == x2)
    {
        if (x1 != 1 && x1 != n)
        {
            cout << -1 << endl;
        }
        else
        {
            if (x1 == 1)
            {
                cout << string(n - 1 , 'R');
                if (y1 == 1)
                {
                    cout << "D";
                }
                else
                {
                    cout << "U";
                }
                cout << string(n - 1, 'L');
            }
            else
            {
                cout << string(n - 1, 'L');
                if (y1 == 1)
                {
                    cout << "D";
                }
                else
                {
                    cout << "U";
                }
                cout << string(n - 1, 'R');
            }
        }
    }
    else
    {
        bool sw = false ; 
        if(x1 > x2)
        {
            sw = true ; 
            swap(x1 , x2) ;
            swap(y1 , y2) ;
        }
        string ans ;
        if(x1 != 1)
        {
            ans += string(x1 - 1 , 'L') ;
            if (y1 == 1)
            {
                ans += "D";
            }
            else
            {
                ans += "U";
            }
            ans += string(x1 - 1 , 'R') ;
        }
        else
        {
            if (y1 == 1)
            {
                ans += "D";
            }
            else
            {
                ans += "U";
            }
        }
        ans += 'R' ;
        for(int i = 1 ; i < (x2 - x1) ; i++)
        {
            if(i & 1)
            {
                ans += (y1 == 1 ? 'U' : 'D') ;
            }
            else
            {
                ans += (y1 == 1 ? 'D' : 'U') ; 
            }
            ans += 'R' ;
        }
        
        
        if(x2 != n)
        {
            ans += string(n - x2 , 'R');
            ans += (y2 == 1 ? 'U' : 'D') ;
            ans += string(n - x2 , 'L') ;
        }
        else
        {
            ans += (y2 == 1 ? 'U' : 'D') ; 
        }
        
        if(sw)
        {
            reverse(all(ans)) ;
            for(int i = 0 ; i < ans.size() ; i++)
            {
                if(ans[i] == 'L')ans[i] = 'R' ;
                else if(ans[i] == 'R')ans[i] = 'L' ;
                else if(ans[i] == 'U')ans[i] = 'D' ;
                else ans[i] = 'U' ;
            }
        }
        cout << ans << endl ; 
    }
}
全部评论

相关推荐

最喜欢秋天的火龙果很...:第一份工作一定要往大的去,工资低点没事。后面换工作会更好找,即使你去小公司,你也不可能不会换工作的。所以找大的去
点赞 评论 收藏
分享
评论
1
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务