2022牛客五一集训派对day1(E、H)

E-Touring cities

链接:https://ac.nowcoder.com/acm/contest/33549/E
来源:牛客网
题目:
Niuniu wants to tour the cities in Moe country. Moe country has a total of nm cities. The positions of the cities form a grid with n rows and m columns. We represent the city in row x and column y as (x,y). (1 ≤ x ≤ n,1 ≤ y ≤ m) There are bidirectional railways between adjacent cities. (x1,y1) and (x2,y2) are called adjacent if and only if |x1-x2|+|y1-y2|=1. There are also K bidirectional air lines between K pairs of cities. It takes Niuniu exactly one day to travel by a single line of railway or airplane. Niuniu starts and ends his tour in (1,1). What is the minimal time Niuniu has to travel between cities so that he can visit every city at least once?
Note that the air line may start and end in the same city.
题意:
给一个n
m的矩形,相邻的方格之间连边,在给k组x1,y1,x2,y2(x1,y1)和(x2,y2)连边,从(1,1)走到(1,1),需要经过所有的方格每次移动一个方格需要1天时间,输出走完这些的最小的天数。
思路:
通过画图自己手动模拟可以发现当n和m不同时为奇数的时候输出nm就是答案,当n和m都为奇数的时候,发现可以构造出nm+1的答案,我们把整张图从(1,1)开始黑白染色当两个黑色块之间有一条边的情况是这个图还是可以构成哈密顿回路既答案可以为n*m,所以我们只需要判断是否有两个黑块存在边就行。
以下为ac代码:

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define int ll
#define pii pair<int,int>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-8;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int LINF=0x3f3f3f3f3f3f3f3f;
const int MAXN=2e5+10;
void solve()
{
    int n,m,k;
    cin>>n>>m>>k;
    if((n&1)&&(m&1))
    {
        int ans=n*m+1;
        int flag=0;
        for(int i=1;i<=k;++i)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
            if(x1==x2&&y1==y2) continue;
            if(x1%2==y1%2&&x2%2==y2%2) flag=1;
        }
        cout<<ans-flag<<"\n";
    }
    else
    {
        for(int i=1;i<=k;++i)
        {
            int x1,y1,x2,y2;
            cin>>x1>>y1>>x2>>y2;
        }
        int ans=n*m;
        cout<<ans<<"\n";
    }
}
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _=1;
    cin>>_;
    for(int i=1; i<=_; ++i)
    {
        solve();
    }
    return 0;
}
/*
*/

H-Playing games

链接:https://ac.nowcoder.com/acm/contest/33549/H
来源:牛客网
题目:
Niuniu likes playing games. He has n piles of stones. The i-th pile has ai stones. He wants to play with his good friend, UinUin. Niuniu can choose some piles out of the n piles. They will play with the chosen piles of stones. UinUin takes the first move. They take turns removing at least one stone from one chosen pile. The player who removes the last stone from the chosen piles wins the game. Niuniu wants to choose the maximum number of piles so that he can make sure he wins the game. Can you help Niuniu choose the piles?
题意:
给定n个数字,从中选出k个然后Niuniu和Uinuin玩尼姆游戏在保证Niuniu必赢的情况下输出最大的k如果Niuniu不能必赢则输出0,其中Niuniu后手
思路:
尼姆游戏后手必赢的情况所有数字的异或和为0,所以我们要选出尽可能多少数字使得他们的异或和为0。我们把所有的数字全部异或起来得到一个异或和sum,然后我们只需要找出最少的数字异或和为sum就行,把n-最少的数字就是最终答案。对于每个数字我们只有选或者不选两种情况,这就是背包由此我们可以写出dp方程式dp[i][j]代表前i个数字异或和为j的情况下选的最少的个数这个dp可以用滚动数组压掉一维。这样的复杂度显然是通过不了的,观察后发现当sum=0时可以直接输出答案n-1,把每个数字a去跟sum异或如果存在sum^a这个值我们可以直接输出n-2,剩下的情况去跑dp,注意dp第二维一定要开(1<<19)不然会炸空间,至于这样为什么能过其实我也不太懂,感觉数字一多必然会出现1和2这两种情况(猜测),数字少的话就让它跑dp,赛后看了大家过得好像都是fwt,但是本人太弱了不会写fwt,如果有大佬能hack的话把数据贴贴。
以下为ac代码:

#include<bits/stdc++.h>
typedef long long ll;
typedef unsigned long long ull;
#define int ll
#define pii pair<int,int>
using namespace std;
const double pi=acos(-1.0);
const double eps=1e-8;
const int mod=1e9+7;
const int INF=0x3f3f3f3f;
const int LINF=0x3f3f3f3f3f3f3f3f;
const int MAXN=5e5+10;
int a[MAXN];
int vis[MAXN];
vector<int>v;
int dp[2][1<<19];
void solve()
{
    int n;
    cin>>n;
    int sum=0;
    for(int i=1; i<=n; ++i)
    {
        cin>>a[i];
        if(!vis[a[i]]) v.push_back(a[i]);
        vis[a[i]]++;
        sum^=a[i];
    }
    if(sum==0) cout<<n;
    else
    {
        if(vis[sum])
        {
            cout<<n-1;
            return ;
        }
        for(int x:v)
        {
            if(vis[sum^x])
            {
                cout<<n-2;
                return ;
            }
        }
        for(int i=0;i<=1;++i)
        {
            for(int j=0;j<(1<<19);++j)
            {
                dp[i][j]=1e18;
            }
        }
        dp[0][0]=0;
        for(int i=0;i<v.size();++i)
        {
            for(int j=0;j<(1<<19);++j)
            {
                if(dp[i%2][j]==1e18) continue;
                dp[(i+1)%2][j]=min(dp[(i+1)%2][j],dp[i%2][j]);
                dp[(i+1)%2][j^v[i]]=min(dp[(i+1)%2][j^v[i]],dp[i%2][j]+1);
            }
        }
        cout<<max(0ll,n-dp[v.size()%2][sum]);
    }
}
signed main()
{
    std::ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int _=1;
    //cin>>_;
    for(int i=1; i<=_; ++i)
    {
        solve();
    }
    return 0;
}
/*
*/
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
牛客 a卷2022年第四季度的华为题目中,要求考生设计一种高效的数据结构,能够支持以下几种操作: 1. 添加一个元素 2. 删除一个元素 3. 查找是否存在某个元素 4. 返回元素的总数 该数据结构要求满足空间复杂度较小、时间复杂度较低、能够快速地进行查找和修改等多种操作。 想要编写这样一种数据结构,我们可以参考许多已有的经典算法与数据结构,如二叉树、哈希表、红黑树等,通过综合利用它们的优点来实现这个问题的解决。 例如,我们可以通过哈希表来存储所有元素的值,并在每个哈希链表的元素中再使用红黑树来进行排序与查找。这样,我们既能够轻松地进行元素的添加和删除操作,也能够在查找较大数据范围和数量时保持较高的速度与效率。同时,由于使用了多个数据结构来协同完成这个问题,我们也能够在空间复杂度上适度地进行优化。 当然,在具体设计这个数据结构的过程中,我们还需要考虑一些实践中的细节问题,例如如何避免哈希冲突、如何处理数据丢失与被删除元素所占用的空间等问题,这都需要相应的算法与流程来进行处理。 总体来看,设计这种支持多种操作的高效数据结构,需要我们具备丰富的算法知识和编程实践能力,同时需要我们在具体处理问题时能够将多种算法和数据结构进行有效地结合。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值