Codefoces Round 900(Div.3) A ~E

A.How Much Does Daytona Cost

思路 : 有 k k k 就输出 y e s yes yes,否则输出 n o no no

    int n, k;
    cin >> n >> k;
    bool flag = false;
    for (int i = 1; i <= n; i++)
    {
        int x;
        cin >> x;
        if (x == k)
        {
            flag = true;
        }
    }
    if (flag)
        cout << "YES" << endl;
    else
        cout << "NO" << endl;

有我没他


B. Aleksa and Stack

思路 : 构造一个数组满足 a i + 2 a_{i + 2} ai+2 不能被 a i + 1 + a i a_{i+1} + a_{i} ai+1+ai 整除。奇数永远不被偶数整除,我们只需要一个正奇数即可

	int n;
    cin >> n;
    int cnt = 2;
    for (int i = 1; i <= n; i++)
    {
        cout << cnt << ' ';
        cnt += 3;
    }
    cout << endl;

奇数永远不会被偶数整除,就像我和她永远没有相交线


C. Vasilije in Cacak

思路 : 只要在能取的最小值和能去的最大值,这个 x x x 就是合法的

	ll n, k, x;
    cin >> n >> k >> x;
    ll a = n + (n * (n - 1)) / 2;
    ll m = n - k;
    ll b = m + (m * (m - 1)) / 2;
    ll c = k + (k * (k - 1))/  2;
    if (a - b < x || c > x)
    {
        cout << "NO" << endl;
    }
    else
    {
        cout << "YES" << endl;
    }

D. Reverse Madness

思路 :每一个区间是不相交且互不干扰的,用差分维护每一区间的需要翻转的区间;区间具有对称性, i i i 始终与 n − i + 1 n - i + 1 ni+1 交换,因此翻转的时候从左边开始往翻转区间的中心点靠近即可。

	int n, k;
	cin >> n >> k;
	string s; cin >> s;
	s = " " + s;
	vector<int> l(n + 1), r(n + 1);
	for (int i = 1; i <= k; i++) {
		cin >> l[i];
	}
	for (int i = 1; i <= k; i++) {
		cin >> r[i];
	}
 
	
	vector<int> b(n + 2);
	int q; cin >> q;
 
	while (q--)
	{
		int x; cin >> x;
		int L = 1,R = k;
		while (L < R) {
			int mid = L + R >> 1;
			if (r[mid] >= x) R = mid;
			else L = mid + 1;
		}
		int ll = min(x, l[L] + r[L] - x);
		int rr = max(x, l[L] + r[L] - x);
 
		b[ll] ++, b[rr + 1]--;
	}
 
	for (int i = 1; i <= n; i++) {
		b[i] += b[i - 1];
	}
 
	for (int i = 1; i <= k; i++) {
		for (int ll = l[i], rr = r[i]; ll <= rr; ll++, rr--) {
			if (b[ll] & 1) {
				swap(s[ll], s[rr]);
			}
		}
	}
	for (int i = 1; i <= n; i++) {
		cout << s[i];
	}
	cout << endl;

E. Iva & Pav

思路1 :经典的线段树 + 二分,超级好写 ,不用懒标记,只需要pushup即可;区间维护异或值,最后用二分查询最右能 ≥ \geq k k k 的区间右值

#include <algorithm>
#include <cmath>
#include <cstring>
#include <iostream>
#include <queue>
#include <set>
#include <stack>
#define fi first
#define se second
#define pb push_back
#define sz size()
#define bpt __builtin_popcountll

using namespace std;
typedef long long ll;
typedef unsigned long long ull;

const int N = 2E5 + 10, INF = 0x3f3f3f3f;

int p[N], inv[N];
int find(int x){if (p[x] != x){ p[x] = find(p[x]);}return p[x];}
int gcd(int a, int b) { return b ? gcd(b, a % b) : a; }
ll ksm(int a, int k, int p){ll res = 1;while (k){if (k & 1){ res = (ll)res * a % p; }k >>= 1;a = (ll)a * a % p;}return res;}
int exgcd(int a, int b, int& x, int& y){if (!b){x = 1, y = 0;return a;}int d = exgcd(b, a % b, y, x);y -= a / b * x;return d;}
void inv_(int p){inv[1] = 1;for (int i = 2; i <= p; i++){inv[i] = (p - p / i) * inv[p % i] % p;}}

struct Node
{
    int l, r;
    ll sum;
} tr[N << 3];

ll a[N];
int x, k;
void pushup(int u)
{
    tr[u].sum = tr[u << 1].sum & tr[u << 1 | 1].sum;
}

void build(int u, int l, int r)
{
    tr[u] = { l, r };
    if (l == r)
    {
        tr[u].sum = a[l];
    }
    else
    {
        int mid = l + r >> 1;
        build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
        pushup(u);
    }
}

ll query(int u, int l, int r)
{
    if (tr[u].l > r || tr[u].r < l)
    {
        return (1 << 31) - 1;
    }
    if (tr[u].l >= l && tr[u].r <= r)
    {
        return tr[u].sum;
    }
    int mid = tr[u].l + tr[u].r >> 1;
    return (query(u << 1, l, r) & query(u << 1 | 1, l, r));
}

bool check(int mid)
{
    if (query(1, x, mid) >= k)
        return true;
    else
        return false;
}
void solve()
{
    int n;
    cin >> n;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }

    build(1, 1, n);

    int q;
    cin >> q;
    while (q--)
    {
        cin >> x >> k;
        if (a[x] < k)
        {
            cout << -1 << endl;
            continue;
        }
        int l = x, r = n;
        while (l <= r)
        {
            int mid = l + r >> 1;
            if (check(mid))
            {
                l = mid + 1;
            }
            else
            {
                r = mid - 1;
            }
        }
        cout << r << endl;
    }
    cout << endl;
}
int main()
{
    int _;
    cin >> _;
    while (_--)
        solve();
    system("pause");
}

思路2 :将数组 a a a 的每一个数的每一位存到数组里面,进行前缀和,同样的用二分查找最右满足条件的区间下标

	int n;
    cin >> n;
    vector<int> a(n);
    
    for (int i = 0; i < n; i++)
    {
        cin >> a[i];
    }
 
    for (int i = 0; i < n; i++) {
        for (int j = 0; j < 30; j++) {
            if (a[i] & (1 << j)) {
                sum[i + 1][j] = sum[i][j] + 1;
            }
            else {
                sum[i + 1][j] = sum[i][j];
            }
        }
    }
 
    int q;
    cin >> q;
    while (q--)
    {
        int l, k;
        cin >> l >> k;
        if (a[l - 1] < k)
        {
            cout << -1 << endl;
            continue;
        }
        int ll = l;
        int rr = n;
        int ans = l;
        while (ll <= rr)
        {
            int mid = ll + rr >> 1;
            int res = 0;
            for (int j = 0; j < 30; j++)
            {
                if (sum[mid][j] - sum[l - 1][j] == mid - l + 1)
                {
                    res += (1 << j);
                }
            }
 
            if (res >= k)
            {
                ll = mid + 1;
                ans = max(ans, mid);
            }
            else
                rr = mid - 1;
        }
        cout << ans << endl;
    }
    cout << endl;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值