Codeforces Round 984 (Div. 3)

Codeforces Round 984 (Div. 3) 总结

https://codeforces.com/contest/2036

A

按题意模拟判断一下即可。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n;
int a[N];
void solve()
{
    cin>>n;
    for(int i=1;i<=n;i++) cin>>a[i];
    for(int i=2;i<=n;i++)
    {
        if(abs(a[i]-a[i-1])!=5&&abs(a[i]-a[i-1])!=7) 
        {
            cout<<"No\n";
            return ;
        }
    }
    cout<<"Yes\n";
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

B

统计每种品牌的总价值,取前 \(n\) 个最大值。数据较小,直接用数组装,排序后取前 \(n\) 大。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
int n,k;
int a[N];
void solve()
{
    cin>>n>>k;
    for(int i=1;i<=k;i++)
    {
        int b,c;
        cin>>b>>c;
        a[b]+=c;
    }
    sort(a+1,a+k+1);
    int ans=0;
    for(int i=k;i>=max(0,k-n+1);i--) ans+=a[i];
    cout<<ans<<'\n';
    for(int i=1;i<=k;i++) a[i]=0;
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

C

先统计有多少个 1100

可以知道,修改过后能影响的范围很小,判断一下改变前后是否是 1100

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=2e5+5;
string s;
int n,q;
bool check(int i)
{
    if(i<1||i+3>n) return 0;
    if(s[i]=='1'&&s[i+1]=='1'&&s[i+2]=='0'&&s[i+3]=='0') return 1;
    return 0;
}
void solve()
{
    cin>>s>>q;
    n=s.size();
    int cnt=0;
    s="0"+s;
    for(int i=1;i<=n-3;i++)
    {
        if(check(i)) cnt++;
    }    
    while(q--)
    {
        int k;
        char x;
        cin>>k>>x;
        if(s[k]!=x)
        {
            if(x=='1')
            {
                if(check(k-3)||check(k-2)) cnt--;
                s[k]=x;
                if(check(k)||check(k-1)) cnt++;
            }
            else 
            {
                if(check(k)||check(k-1)) cnt--;
                s[k]=x;
                if(check(k-3)||check(k-2)) cnt++;
                
            }
        }
        if(cnt) cout<<"Yes\n";
        else cout<<"No\n";
    }
    
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

D

将每一层的数据按顺时针提出来,因为只要判断 \(4\) 位,所以在最后加上前三个数,断环成链。统计有多少个 1543

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1005,M=5005;
int n,m;
string g[N];
char a[M];
bool check(int i)
{
    if(a[i]=='1'&&a[i+1]=='5'&&a[i+2]=='4'&&a[i+3]=='3') return 1;
    return 0;
}
void solve()
{
    cin>>n>>m;
    int cnt=n*m;
    for(int i=0;i<n;i++) cin>>g[i];
    int s=0,ans=0;
    while(cnt)
    {
        int tot=0;
        int x=s,y=s-1;
        while(y+1<m-s) a[++tot]=g[x][++y],cnt--;
        while(x+1<n-s) a[++tot]=g[++x][y],cnt--;
        while(y-1>=s) a[++tot]=g[x][--y],cnt--;
        while(x-1>s) a[++tot]=g[--x][y],cnt--;
        a[++tot]=a[1],a[++tot]=a[2],a[++tot]=a[3];
        for(int i=1;i<=tot-3;i++) if(check(i)) ans++;
        s++;
    }
    cout<<ans<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

E

先预处理 \(b_{i,j}\) 出来。

按位或的大小单调不减,可以二分确定范围,要注意 \(j\) 要作为第一维,便于二分查找。要注意一下边界问题,tourist 都吃罚时了 qwq。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1e5+5;
int n,m,q;
vector<vector<int> >g;

void solve()
{
    cin>>n>>m>>q;
    g.resize(m);
    for(int j=0;j<m;j++) g[j].resize(n); 
    for(int i=0;i<n;i++)
        for(int j=0;j<m;j++) 
            cin>>g[j][i];
    for(int j=0;j<m;j++)
        for(int i=1;i<n;i++)
            g[j][i]|=g[j][i-1];
    while(q--)
    {
        int l=1,r=n,st=0;
        int m;
        int x,y;
        char op;
        cin>>m;
        while(m--)
        {
            cin>>x>>op>>y;
            x--;
            if(op=='<') 
            {
                int id=lower_bound(g[x].begin(),g[x].end(),y)-g[x].begin();
                if(id<1) st=1;
                else r=min(r,id);
            }
            else 
            {
                int id=upper_bound(g[x].begin(),g[x].end(),y)-g[x].begin()+1;
                if(id>n) st=1;
                else l=max(l,id);
            }   
        }
        if(l<=r&&st==0) cout<<l<<'\n';
        else cout<<-1<<'\n';
    }
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    solve();
    return 0;
}

F

\(f(l, r) = l \oplus (l+1) \oplus \dots \oplus r\)\(\oplus\) 表示按位异或。

神奇的规律:

\[ f(0, x) = \begin{cases} x & x \equiv 0 \pmod{4} \\ 1 & x \equiv 1 \pmod{4} \\ x + 1 & x \equiv 2 \pmod{4} \\ 0 & x \equiv 3 \pmod{4} \end{cases} \]

可以打表找规律。或者利用连续四个自然数异或和为 \(0\) 来推导。
这篇博客有详细证明:https://www.cnblogs.com/Mychael/p/8633365.html

因为 \(a \oplus a=0\),所以 \(f(l,r)=f(0,r) \oplus f(0,l-1)\)

直接求满足 \(x \not\equiv k \mod 2^i\)\(x\) 不好求,但是可以求 \(x \equiv k \mod 2^i\)\(x\)\([l,r]\)\(k\) 的超集,后 \(i\) 位与 \(k\) 相同。设 \(x=k+j \times 2^i\)\(j\) 的范围为 \(\LARGE[\large\left\lceil \frac{l - k}{2^i} \right\rceil , \left\lfloor \frac{r - k}{2^i} \right\rfloor\LARGE]\)

\(x\) 拆成两部分,二进制下后面 \(i\) 位都一样,所以要看 \(x\) 的范围大小是奇数还是偶数,是奇数的话后 \(i\) 位异或和就是 \(k\)。其他位就是算 \(j\) 的异或和,最后乘上 \(2^i\) 就行。\(j\) 的异或和也是那样算的。

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>

using namespace std;
typedef long long ll;
const int N=1;
ll l,r,i,k;
ll pre(ll x)
{
    if(x<=0) return 0;
    if(x%4==1) return 1;
    if(x%4==2) return x+1;
    if(x%4==3) return 0;
    return x;
}
void solve()
{
    cin>>l>>r>>i>>k;
    ll ans=pre(r)^pre(l-1);
    r=(r-k)>>i,l=((l-k+(1ll<<i)-1)>>i);
    if(l<0) l=0;
    if(r-l+1&1) ans^=k;
    ans^=(pre(r)^pre(l-1))<<i;
    cout<<ans<<'\n';
}
int main ()
{
    #ifndef ONLINE_JUDGE
    freopen("1.in","r",stdin);
    freopen("1.out","w",stdout);
    #endif 
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    int T;
    cin>>T;
    while(T--) solve();
    return 0;
}

posted @ 2024-11-22 13:41  zhouruoheng  阅读(3)  评论(0编辑  收藏  举报