2024牛客多校2

E
打表发现,将 x 化成二进制后,将 x 最低位的 1 变成 0 一定满足条件。当 x 为 2 的幂时找不到满足条件的 y。
即当 x 不是 2 的幂时,满足条件的 y=x-lowbit(x),x 是 2 的幂时无解。

#include<bits/stdc++.h>
#define endl '\n'

using namespace std;
using ll = long long;

void solve()
{
   ll x; cin>>x;
   ll ans=x-(x&(-x)); //位运算加括号
   ll sig=x&(x-1); // 判断是不是 2 的幂
   if(!sig) cout<<-1<<endl;
   else cout<<ans<<endl;
   return ;
}

int main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T; cin>>T;
    while(T--) solve();
    return 0;
}

C
简单动态规划,由于向左走和向右走互逆,对于每个点只考虑向右走的情况。
遍历上下两条路径即可,如果上下两条路可以同时向右走,那么,每个点可以由左边直接过来,也可以从另一边绕路过来,这样可能会更远。递推即可。

#include<bits/stdc++.h>
#define endl '\n'
#define int long long

using namespace std;

const int maxn = 1e6+3;
char s[3][maxn];
int dp[3][maxn];

void solve()
{
    int n; cin>>n;
    string t;
    for(int i=1;i<=2;i++)
    {
        cin>>t;
        for(int j=1;j<=t.length();j++)
        s[i][j]=t[j-1];
    }
    int ans=-1;
    for(int i=1;i<=n;i++)
    {
        int x=s[1][i]=='R';
        int y=s[2][i]=='R';
        if(x) dp[1][i]=dp[1][i-1]+1;
        if(y) dp[2][i]=dp[2][i-1]+1;
        if(x&&y)
        {
            dp[1][i]=max(dp[1][i],dp[2][i-1]+2);
            dp[2][i]=max(dp[2][i],dp[1][i-1]+2);
        }
        ans=max(ans,max(dp[1][i],dp[2][i]));
    }
    cout<<max(0ll,ans-1ll)<<endl;
    return ;
}

signed main()
{
    ios::sync_with_stdio(0),cin.tie(0),cout.tie(0);
    int T; T=1;
    while(T--) solve();
    return 0;
}

H
前缀和,考虑对所有的操作做一个前缀,问题变成能不能找到一段区间使得区间和为 [ x , y ] [x,y] [x,y],注意查询的时候不能从前往后遍历,这样会有重复的情况,比如此时遍历的 s 3 s3 s3 s 3 s3 s3 减去目标坐标 [ x , y ] [x,y] [x,y] 后得到 s 1 s1 s1,这时候把 s 1 s1 s1 的所有情况都遍历了一遍,但后面再遍历到 s 6 s6 s6 的时候如果减去目标坐标还是 s 1 s1 s1 这样又把 s 1 s1 s1 s 6 s6 s6 多算了进去,从后往前就不会出现重复的情况,因为 p o s pos pos 数组记录的是这个坐标最早出现的位置。

#include<bits/stdc++.h>
#define endl '\n'

using namespace std; 
using pii=pair<int,int>;
 
const int N=2e5+7;
int n,x,y;
string s;
 
pii operator +(const pii &a,const pii &b)
{
    return {a.first+b.first,a.second+b.second};
}
 
pii sf[N];
map<char,pii> dir;

int main()
{

    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>x>>y;
    cin>>s;
    s=' '+s;
    if(!x&&!y)
    {
        cout<<1ll*n*(n+1)/2<<"\n";
        return 0;
    }
    dir['A']={-1,0};
    dir['D']={1,0};
    dir['W']={0,1};
    dir['S']={0,-1};
    for(int i=1;i<=n;i++)
    sf[i]=sf[i-1]+dir[s[i]];
    long long ans=0;
    map<pii,int> pos;
    for(int i=n;i>=1;i--)
    {
        pos[sf[i]]=i;
        auto [xi,yi]=sf[i-1];
        pii q(xi+x,yi+y);
        if(pos.count(q))
        ans+=n-pos[q]+1;
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值