• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
nannandbk
博客园    首页    新随笔    联系   管理    订阅  订阅
AtCoder Beginner Contest 330 ABCDE

AtCoder Beginner Contest 330 ABCDE

A - Counting Passes

签到题,不多说。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n,m; cin>>n>>m;
    int cnt = 0;
    for(int i = 1;i <= n; i++)
    {
        int x; cin>>x;
        cnt += (x >= m);
    }
    cout<<cnt<<"\n";


    return 0;
}

B - Minimize Abs 1

题意:有一个长为 \(N\) 的数列 \(A\) 和两个整数 \(L,R\)。对于每个 \(A_{i}\),你需要选出一个数 \(X_{i}\),满足如下条件:

  • \(L\le X_{i}\le R\)
  • 对于所有整数 \(L\le Y\le R\),\(|X_{i}-A_{i}|\le|Y-A_i|\)

思路:二分

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n,l,r; cin>>n>>l>>r;
    for(int i = 1;i <= n; i++)
    {
        int x; cin>>x;
        int L = l,R = r;
        while(L<=R)
        {
            int mid = (L+R)/2;
            if(mid >= x) R = mid-1;
            else L = mid+1;
        }
        cout<<min(r,R+1)<<" ";
    }


    return 0;
}

C - Minimize Abs 2

题意:给你一个整数\(D\),找到对于非负整数\(x,y\)的\(|x^2+y^2-D|\)的最小值

思路:相比上一题,这是2个数,怎么办哩。可以考虑枚举x,二分y。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;

int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    ll n; cin>>n;
    ll ans = 1e18;
    for(ll i = 1;i*i <= n; i++)
    {
        ll x = i;
        ll l = 0,r = 1e6;
        while(l<=r)
        {
            ll mid = (l+r)>>1;
            if(mid*mid+x*x >= n)r = mid-1;
            else l = mid+1;
        }
        //cout<<"x = "<<x<<" r+1 = "<<r+1<<"\n";
        ans = min({ans,min(abs(x*x+r*r-n),abs(x*x+(r+1)*(r+1)-n))});
    }
    cout<<ans<<"\n";

    return 0;
}

D - Counting Ls

题意:现有一个 \(N\) 行 \(N\) 列的字符数组,满足对于每个 \(1 \le i \le N,1 \le j \le N\) 都有 $ S_{i,j} \in {o,x} $

请问在该数组里有多少个满足以下条件的三方格组:

  • 三个格子内都是 \(o\)

  • 三个方格互不相同

  • 恰好有两个方格在同一行

  • 恰好有两个方格在同一列

思路:藕一开始的思路是,可以先用前缀和求出每个点朝四个方向的贡献,然后加起来。

下面是藕写的依托答辩QAQ...

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
char a[2010][2010];
int b[2010][2010],b1[2010][2010],b2[2010][2010],b3[2010][2010];
int c[2010][2010],c1[2010][2010],c2[2010][2010],c3[2010][2010];
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n; cin>>n;
    for(int i = 1;i <= n; i++)
        for(int j = 1;j <= n; j++)
            cin>>a[i][j];
    for(int i = 1;i <= n; i++)
    {
        for(int j = n;j >= 1; j--)
        {
            b[i][j] = b[i][j+1]+(a[i][j]=='o');
        }
    }

    for(int j = 1;j <= n; j++)
    {
        for(int i = n;i >= 1; i--)
        {
            c[i][j] = c[i+1][j]+(a[i][j]=='o');
        }
    }

    for(int i = n;i >= 1; i--)
    {
        for(int j = 1;j <= n; j++)
        {
            b1[i][j] = b1[i][j-1]+(a[i][j]=='o');
        }
    }

    for(int j = n;j >= 1; j--)
    {
        for(int i = 1;i <= n; i++)
        {
            c1[i][j] = c1[i-1][j]+(a[i][j]=='o');
        }
    }


    for(int i = n;i >= 1; i--)
    {
        for(int j = n;j >= 1; j--)
        {
            b2[i][j] = b2[i][j+1]+(a[i][j]=='o');
        }
    }

    for(int j = 1;j <= n ; j++)
    {
        for(int i = 1;i <= n; i++)
        {
            c2[i][j] = c2[i-1][j]+(a[i][j]=='o');
        }
    }


    for(int i = 1;i <= n; i++)
    {
        for(int j = 1;j <= n; j++)
        {
            b3[i][j] = b3[i][j-1]+(a[i][j]=='o');
        }
    }

    for(int j = n;j >= 1 ; j--)
    {
        for(int i = n;i >= 1; i--)
        {
            c3[i][j] = c3[i+1][j]+(a[i][j]=='o');
        }
    }


    // for(int i = 1;i <= n; i++)
    // {
    //     for(int j = 1;j <= n; j++)
    //         cout<<b[i][j]<<" ";
    //     cout<<"\n";
    // }

    ll ans = 0;
    for(int i = 1;i <= n; i++)
    {
        for(int j = 1;j <= n; j++)
        {
            if(a[i][j]=='o'){
                ans += (b[i][j]-1)*(c[i][j]-1);
                ans += (b1[i][j]-1)*(c1[i][j]-1);
                ans += (b2[i][j]-1)*(c2[i][j]-1);
                ans += (b3[i][j]-1)*(c3[i][j]-1);
                
            }
        }
    }

   
    cout<<ans<<"\n";
    return 0;
}

但是想想其实没有那么复杂,因为不用考虑方向呀,直接统计行列的贡献即可。

// AC one more times
// nndbk
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int N = 2e5 + 10;
char a[2010][2010];
int r[2010],c[2010];
int main()
{
    ios::sync_with_stdio(false);   cin.tie(nullptr), cout.tie(nullptr);
    int n; cin>>n;
    for(int i = 1;i <= n; i++)
        for(int j = 1;j <= n; j++)
            cin>>a[i][j];
    for(int i = 1;i <= n; i++)
    {
        for(int j = 1;j <= n; j++)
        {
            if(a[i][j]=='o')
                r[i]++,c[j]++;
        }
    }
    ll ans = 0;
    for(int i = 1;i <= n; i++)
        for(int j = 1;j <= n; j++)if(a[i][j]=='o'){
            ans += (r[i]-1)*(c[j]-1);
        }
    cout<<ans<<"\n";
    return 0;
}

E - Mex and Update

题意:给定一个序列,支持单点修改,每次修改后输出全局 \(\operatorname{mex}\)。

一个序列的 \(\operatorname{mex}\) 定义为,序列中最小的没有出现过的非负整数。

思路:权值树状数组+二分,具体看代码。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 201000;
template<class T>
struct BIT {
    T c[N];
    int size;
    void resize(int s) { size = s;}
    T query(int x) { // 1 ... x
        assert(x <= size);
        T s = 0;
        for (; x; x -= x & (-x)) {
        s += c[x];
    }
    return s;
    }

    void modify(int x, T s) { // a[x] += s
        assert(x != 0);
        for (; x <= size; x += x & (-x)) {
            c[x] += s;
        }
    } 
};

BIT<ll> tr;
int n,q,a[N],vis[N];
int main()
{
	ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>n>>q;
	tr.resize(n+1);
	for(int i = 1;i <= n; i++)
	{
		cin>>a[i];
		a[i]++;//树状数组1 base的
		a[i] = min(a[i],n+1);//虽然a[i]范围很大,但是mex的值只会在n+1以内。
		vis[a[i]]++;
		if(vis[a[i]]==1)tr.modify(a[i],1);//存在改为1
	}

	while(q--)
	{
		int i,x; cin>>i>>x;
		x = min(x,n+1);
		x++;
		vis[a[i]]--;
		if(vis[a[i]]==0)tr.modify(a[i],-1);
		a[i] = x;
		vis[a[i]]++;
		if(vis[a[i]]==1)tr.modify(a[i],1);

		int l = 1,r = n+1;
		while(l<=r)
		{
			int mid = (l+r)/2;
			if(tr.query(mid) == mid) l = mid+1;
			else r = mid-1;
		}
		cout<<l-1<<"\n";
	}

	return 0;
}
posted on 2024-02-01 22:29  nannandbk  阅读(24)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3