week17

 1.碰撞2

 思路:

只要一条线上方向向右的最左边的人的x坐标大于方向向左的最右边人的坐标就不会撞上,根据这个依据判断即可

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long 
map<int,pair<int,int>>jilu;
vector<pair<int, int>>shujv;
signed main() {
	int n;
	cin >> n;
	int n1 = n;
	while (n1--) {
		int a, b;
		cin >> a >> b;
		shujv.push_back(make_pair(a, b));
	}
	string c;
	cin >> c;
	for (int e = 0; e < n; e++) {
		int a, b;
		a = shujv[e].first;
		b = shujv[e].second;
		if (c[e] == 'L') {
			if (jilu[b].first < a) {
				jilu[b].first = a;
			}
		}
		else {
			if (a == 0) {
				jilu[b].second = -1;
			}
			if (jilu[b].second == 0) {
				jilu[b].second = a;
			}
			if (jilu[b].second > a) {
				jilu[b].second = a;
			}
		}
		int bijiao1 = jilu[b].first, bijiao2 = jilu[b].second;
		//cout << bijiao1 << " " << bijiao2 << endl;
		if (bijiao1 == 0 || bijiao2 == 0) {
		}
		else {
		if (bijiao1 >= bijiao2) {
			cout << "Yes";
			return 0;
		}
		}
	}
	cout << "No";
	return 0;
}

2.优美!最长上升子序列

 思路:

动态规划扫一遍,主要问题是超时,需要控制外循环为从小到大每个数,内循环为外循环数的倍数,其他要求按题目的要求判断即可

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
	int n;
	cin >> n;
	int n1 = n;
	while (n1--) {
		int a1;
		cin >>a1;
		vector<int>shujv(a1 + 1), pd(a1 + 1, 1);
		for (int e = 1; e <= a1; e++) {
			scanf("%d", &shujv[e]);
		}
		int mx = 1;
		pd[1] = 1;
		for (int e = 1; e <=a1; e++) {
			for (int j = e * 2; j <= a1; j += e)
			{
				if (shujv[j] > shujv[e])pd[j] = max(pd[j], pd[e] + 1);
				mx = max(mx,pd[j]);
			}
		}
		printf("%d\n", mx);
	}
}

3.巨大的牛棚

 思路:

暴力算会超时,所以预处理一下数据,如果没有数就把二维数组中对应的数据存为0,有树就存为1;然后建立一个二维数组,每个位置表示从1,1点一直到该位置的一个行列式的和,然后用二分法处理长度,最后输出左值

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
int q, n;
int ycl[1005][1005];
int zhi[1005][1005];
int check(int mid) {
	for (int e = mid; e <= q; e++) {
		for (int i = mid; i <= q; i++) {
			if (ycl[e][i] - ycl[e - mid][i] - ycl[e][i - mid] + ycl[e - mid][i - mid] == 0) {
				return 1;
			}
		}
	}
	return 0;
}
signed main() {
	cin >> q >> n;
	int n1 = n;
	vector<vector<int>>tu;
	while (n1--) {
		int a, b;
		cin >> a >> b;
		zhi[a][b] = 1;
	}
	for (int e = 1; e <= q; e++) {
		for (int i = 1; i <= q; i++) {
			ycl[e][i] = ycl[e - 1][i] + ycl[e][i - 1] - ycl[e - 1][i - 1] + zhi[e][i];
		}
	}
	int l = 1,r=q;
	while (l +1< r) {
		int mid = (l + r) / 2;
		if (check(mid)) {
			l = mid;
		}
		else {
			r = mid;
		}

	}
	cout << l;
	return 0;
}

4.高利贷

 思路:

套公式,二分法,注意cout的输出小数可能不全

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
double a, b, c;
int check(double mid) {
	double lv = 1 / (1 + mid);
	double a1 = b / (1 + mid);
	double shang = a1 * (1 - pow(lv, c));
	double xia = 1 - lv;
	double jie = shang / xia;
	if (jie > a) {
		return 1;
	}
	return 0;
}
signed main() {
	cin >> a >> b >> c;
	double l = 0, r = 10;
	while (r - l >=1e-9) {
		double mid = l + r;
		mid /= 2;
		if (check(mid)) {
			l = mid;
		}
		else {
			r = mid;
		}

	}
	printf("%.8lf", l);
}

5.背包

思路:

本来以为是背包问题,没想到是逻辑问题,如果遇到大于w/2小于w直接判YES,遇到大于W的不用管,遇到小于w/2的加到和上,如果he>w/2,则YES,否则NO

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
#define int long long
signed main() {
	int asdf;
	cin >> asdf;
	while (asdf--) {
		int n,w;
		cin >> n>>w;
		int n1 = n;
		vector<int>shujv;
		while (n1--) {
			int b;
			cin >> b;
			shujv.push_back(b);
		}
		int he=0;
		int panduan = 1;
		for (int e = 0; e < n; e++) {
			if (shujv[e]*2 >w) {
				if (shujv[e] <= w) {
				panduan = 0;
				cout << "YES" << endl;
				break;
				}
			}
			else {
				if (he + shujv[e] <= w) {
					he += shujv[e];
				}
				if (he*2 >= w) {
					panduan = 0;
					cout << "YES" << endl;
					break;
				}
			}
		}
		if (panduan) {
		cout << "NO" << endl;
		}
	}
}

6.三回文序列

思路:

先遍历一遍数组,记录每个元素的出现次数,然后枚举所有的数作为a(三回文是一种aba形式的字符串),每次枚举把两边的a的个数都算出来,再枚举中间的b的个数,取总和最大值

#define _CRT_SECURE_NO_WARNINGS
#include<bits/stdc++.h>
using namespace std;
int n;
int change(vector<int>v, int ans, vector<int>nums)
{
    int l = 0, r = n - 1, cnt = 0, res = nums[ans];
    while (l < r)
    {
        while (l < r && v[l] != ans)
        {
            nums[v[l]]--;
            l++;
        }
        while (l < r && v[r] != ans)
        {
            nums[v[r]]--;
            r--;
        }
        cnt += min(nums[ans], 2);
        nums[ans] -= 2;
        l++, r--;
        for (int i = 1; i <= 26; i++)res = max(res, cnt + nums[i]);
    }
    return res;
}
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    int t;
    cin >> t;
    while (t--)
    {
        cin >> n;
        vector<int>v(n), nums(27);
        for (int i = 0; i < n; i++)
        {
            cin >> v[i];
            nums[v[i]]++;
        }
        int res = 0;
        for (int i = 1; i < 27; i++)
        {
            if (nums[i] != 0)
                res = max(res, change(v, i, nums));
        }
        cout << res << endl;
    }
    return 0;
}

7.简单的异或问题

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
typedef long long ll;
int main()
{
    ll n, m;
    cin >> n >> m;
    ll res = 1;
    res <<= m;
    if (m == 1 && n == 0)
    {
        cout << 1 << endl;
    }
    else if (m == 1 && n == 1)
    {
        cout << 2 << endl;
    }
    else cout << (1LL) * (res - min(n, 1LL)) << endl;
    return 0;
}

8.子串的循环挪动

思路:

我们也可以把需要挪动的子串分成两部分,长度为k的s2尾部子串(将要挪去前面的那部分),和将要从前面移动到后面的s2的头部子串,所以我们整体可以把字符串分成三部分:s的头部s1,需要挪动的子串的头部s2,需要挪动的子串的尾部s3,s的尾部s4.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    string str;
    cin >> str;
    int m, n = str.size();
    cin >> m;
    while (m--)
    {
        int l, r, k;
        cin >> l >> r >> k;
        int mod = (r - l + 1);
        string s1 = str.substr(0, l - 1);
        string s2 = str.substr(l - 1, r - l - (k % mod) + 1);
        string s3 = str.substr(r - k % mod, k % mod);
        string s4 = str.substr(r, n - r + 1);
        if (l != r)
            str = s1 + s3 + s2 + s4;

    }
    cout << str << endl;
    return 0;
}

9.弗拉德和糖果 II

思路:

我们只用判断最大值与其他值的和的关系即可.

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
const int MOD = 1e9 + 7, N = 1e6 + 10;
inline int read() {
    int x = 0; char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') x = (x << 3) + (x << 1) + ch - '0', ch = getchar();
    return x;
}

int main()
{
    int n;
    long long sum = 0, mx = 0, num;
    n = read();
    for (int i = 0; i < n; i++)
    {
        num = read();
        if (mx < num)
        {
            sum += mx;
            mx = num;
        }
        else sum += num;
    }
    if ((n == 1 && mx == 1) || mx <= sum + 1)
    {
        puts("YES");
    }
    else
    {
        puts("NO");
    }
    return 0;
}

 10.上帝的集合

#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
using namespace std;
#include<queue>
#define endl '\n';
typedef long long ll;
typedef pair<ll, ll>PII;
const int N = 1e6 + 10;
int main()
{
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout.tie(nullptr);
    ll t, add = 0;
    priority_queue<ll, vector<ll>, greater<ll>>que;
    cin >> t;
    while (t--)
    {
        int st;
        cin >> st;
        if (st == 1)
        {
            ll x;
            cin >> x;
            que.push(x - add);
        }
        else if (st == 2)
        {
            ll x;
            cin >> x;
            add += x;
        }
        else
        {
            cout << que.top() + add << endl;
            que.pop();
        }
    }

    return 0;
}

猜你喜欢

转载自blog.csdn.net/sign_river/article/details/130172019