首页 > 其他分享 >2020 CSP-J

2020 CSP-J

时间:2024-01-15 23:02:31浏览次数:26  
标签:10 le val int stk tag 2020 CSP

2020 CSP-J

P7071 优秀的拆分(语法)

题意

给定一个正整数,输出二进制拆分。如果这个数是奇数输出 -1

数据规模与约定

对于 \(100\%\) 的数据,\(1 \le n \le 10^7\)。

题解

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
void Solve(void)
{
	int n; cin >> n;
	if (n & 1)
	{
		cout << "-1" << endl;
	}
	else
	{
		for (int i = 30; i >= 0; --i)
		{
			if (n & (1 << i))
			{
				n -= (1 << i);
				cout << (1 << i) << " ";
			}
		}
	}
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P7072 直播获奖(模拟,桶排)

题意

给定一个长度为 \(n\) 的序列 \(a_i\),给定一个百分比 \(w\%\)。对于序列的每一个前缀 \(a_1 ... a_i\),求出第 \(\max(1, \lfloor i \times w \%\rfloor)\) 大的数是多少。

数据规模与约定

对于 \(100\%\) 的数据,\(1 \le n \le 10^5,0 \le a_i \le 6 * 10^2,1 \le w \le 99\)。

题解

动态求动态第 \(k\) 大,因为 \(k\) 不固定,所以不能使用对顶堆。每一次都 sort 一次会超时。考虑使用数据结构,权值线段树或平衡树之类的。考虑到题目给的范围 \(1 \le a_i \le 600\),我们可以每次进行桶排。复杂度为 \(O(600* n)\)。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 1e5 + 10;
const int A = 6e2 + 10;
/*====================*/
int n, w;
int arr[N];
int cnt[A];
/*====================*/
void Solve(void)
{
	cin >> n >> w;
	for (int i = 1; i <= n; ++i)
	{
		cin >> arr[i];
	}

	for (int i = 1; i <= n; ++i)
	{
		cnt[arr[i]]++;
		int person= max(1, i * w / 100);
		for (int j = 600; j >= 0; --j)
		{
			person -= cnt[j];
			if (person <= 0)
			{
				cout << j << " "; break;
			}
		}
	}
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P7073 表达式(模拟,栈,树上前缀和,贪心,表达式求值,后缀表达式)

题意

给定一个逻辑表达式的后缀表达形式和其中每一个变量的初值。

\(q\) 次独立询问,每次询问取反某一个变量的值时,原表达式的值为多少。

数据规模与约定

对于 \(100\%\) 的数据,\(1 \le |s| \le 1 \times 10^6\),\(1 \le q \le 1 \times 10^5\),\(2 \le n \le 1 \times 10^5\)。

题解

首先对字符串进行处理。这里写一个 string 转 int 即可。

将后缀表达式转化成树的形态,建树。

我们发现:

  1. 当运算为 & 时,如果其中一边为 \(0\),另一边无论取何值都不会对结果产生影响。

  2. 当运算为 | 时,如果其中一边为 \(1\),另一边无论取何值都不会对结果产生影响。

  3. 反之,取反操作一定会对结果产生影响。

将无论如何修改都不产生影响的子树标记一下,因为每次询问独立,所以只需要查询该变量叶子节点到根节点的路径上是否是有被标记的节点即可。这里使用树上前缀和加速,每次可以 \(O(1)\) 查询。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 1e5 + 10;
/*====================*/
int n; string expression;
/*====================*/
struct Node
{
	int val = 0;
	char tag = ' ';
	bool useless = false;
	Node * lch = NULL, * rch = NULL;
};
Node* leaf[N];
/*====================*/
stack<Node*>stk;
/*====================*/
int string_to_int(string str)
{
	int res = 0;
	for (auto c : str)
	{
		res = res * 10 + c - '0';
	}
	return res;
}
/*====================*/
void DFS(Node* pre, Node* cur)
{
	if (cur != NULL)
	{
		if (pre != NULL)
		{
			cur->useless |= pre->useless;
		}
		DFS(cur, cur->lch);
		DFS(cur, cur->rch);
	}
}
/*====================*/
void Solve(void)
{
	do
	{
		getline(cin, expression); cin >> n;
		for (int i = 1; i <= n; ++i)
		{
			leaf[i] = new Node;
			cin >> leaf[i]->val;
		}
	} while (false);

	do
	{
		int last = -1; expression.push_back(' ');
		for (int i = 0; i < expression.size(); ++i)
		{
			if (expression[i] == ' ')
			{
				int l = last + 1, r = i - 1; last = i;
				string str = expression.substr(l, r - l + 1);
				if (str[0] == 'x')
				{
					stk.push(leaf[string_to_int(str.substr(1, str.size() - 1))]);
				}
				else
				{
					Node* root = new Node;
					root->tag = str[0];
					if (str == "!")
					{
						Node* cur = stk.top(); stk.pop();
						root->lch = cur;
						root->val = cur->val ^ 1;
					}
					if (str == "&")
					{
						Node* cur1 = stk.top(); stk.pop();
						Node* cur2 = stk.top(); stk.pop();
						root->lch = cur1; root->rch = cur2;
						root->val = cur1->val & cur2->val;
						if (cur1->val == 0)cur2->useless = true;
						if (cur2->val == 0)cur1->useless = true;
					}
					if (str == "|")
					{
						Node* cur1 = stk.top(); stk.pop();
						Node* cur2 = stk.top(); stk.pop();
						root->lch = cur1; root->rch = cur2;
						root->val = cur1->val | cur2->val;
						if (cur1->val == 1)cur2->useless = true;
						if (cur2->val == 1)cur1->useless = true;
					}
					stk.push(root);
				}
			}
		}
		DFS(NULL, stk.top());
	} while (false);
	
	do
	{
		int q; cin >> q;
		while (q--)
		{
			int x; cin >> x;
			if (leaf[x]->useless)
			{
				cout << (stk.top()->val) << endl;
			}
			else
			{
				cout << (stk.top()->val ^ 1) << endl;
			}
		}
	} while (false);
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

P7074 方格取数(dp)

题意

设有 \(n \times m\) 的方格图,每个方格中都有一个整数(有正有负)。从图的左上角走到右下角,每一步只能向上、向下或向右走一格,并且不能重复经过已经走过的方格,也不能走出边界。求取到的整数之和的最大值。

数据规模与约定

对于 \(100\%\) 的数据,\(1 \le n,m \le 10^3\)。方格中整数的绝对值不超过 \(10^4\)。

题解

如果只能向上或者只能向下,这题就是过河卒了。但是现在既能向上也能向下,思考一下怎么处理。

我们发现不能重复经过已经走过的方格,且只能向右走。所以当我们来到 \((i,j)\) 时,只能从左边,或者上面或者下面来到当前点。不存在一上一下的情况,因为不能重复经过已经走过的方格。所以我们将 dp 状态加上一维从上面来还是从下面来。明确状态意义后,转移方程很好想。因为边界处理比较麻烦,这里我使用了记忆化搜索的方式实现 dp。

#include<bits/stdc++.h>
using namespace std;
/*====================*/
#define endl "\n"
/*====================*/
typedef long long lnt;
/*====================*/
const int N = 1e3 + 10;
const int M = 1e3 + 10;
/*====================*/
const lnt INF = 0X7F7F7F7F;
/*====================*/
int n, m;
lnt val[N][M];
/*====================*/
lnt dp[N][M][2];
bool vis[N][M][2];
lnt DP(int i, int j, int tag)
{
	if (i == 1 && j == 1)return val[i][j];
	if (i<1 || i>n || j<1 || j>m)return -INF;
	if (!vis[i][j][tag])
	{
		vis[i][j][tag] = true;
		dp[i][j][tag] = max(DP(i, j - 1, 0), DP(i, j - 1, 1));
		if (tag == 0)
		{
			dp[i][j][tag] = max(dp[i][j][tag], DP(i - 1, j, tag)) + val[i][j];
		}
		if (tag == 1)
		{
			dp[i][j][tag] = max(dp[i][j][tag], DP(i + 1, j, tag)) + val[i][j];
		}
	}
	return dp[i][j][tag];
}
/*====================*/
void Solve(void)
{
	cin >> n >> m;
	for (int i = 1; i <= n; ++i)
	{
		for (int j = 1; j <= m; ++j)
		{
			cin >> val[i][j];
		}
	}
	cout << max(DP(n, m, 0), DP(n, m, 1)) << endl;
}
/*====================*/
int main()
{
#ifndef ONLINE_JUDGE
	freopen("IN.txt", "r+", stdin);
#endif
	ios::sync_with_stdio(false);
	cin.tie(NULL), cout.tie(NULL);
	int T = 1; //cin >> T;
	while (T--)Solve();
	return 0;
}

标签:10,le,val,int,stk,tag,2020,CSP
From: https://www.cnblogs.com/ProtectEMmm/p/17966605

相关文章

  • 2021 CSP-J
    2021CSP-JP7909分糖果(数学)题意给定\(n,l,r\),求一个数\(x\),当\(l\lex\ler\)时,最大的\(x\bmodn\)。数据规模与约定对于\(100\%\)的数据,\(1\len\lel\ler\le10^9\)。题解假设\(l=K_l*n+R_l,r=K_r*n+R_r,x=K_x*n+R_x\)。我们要求......
  • 2022 CSP-J
    2022CSP-JP8813乘方(数学,模拟)题意给定两个数\(a,b\),如果\(a^b\le10^9\),输出\(a^b\)的值。否则输出\(-1\)。数据规模与约定对于\(100\%\)的数据,\(1\lea,b\le10^9\)。题解记得开longlong。如果\(a=1\),那么无论\(b\)是多少结果都是\(1\)。如果\(a\ne......
  • 2023 CSP-J
    2023CSP-JP9748小苹果(模拟)题意\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\)。每天从左侧第\(1\)个苹果开始,每隔\(2\)个苹果拿走\(1\)个苹果。求出多少天能拿完所有的苹果,编号为\(n\)的苹果是在第几天被拿走。数据规模与约定对于\(100\%\)的数据,\(1\l......
  • 2019 CSP-J
    2019CSP-JP5660数字游戏(语法)题意给定一个长度最大为\(8\)的01字符串,求字符串中有多少个\(1\)。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/typedeflonglonglnt;/*===================......
  • 2019 CSP-J 江西
    2019CSP-J江西P5681面积(语法)题意求出边长为\(a\)的正方形与长宽分别为\(b,c\)的矩形哪一个面积更大。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/typedeflonglonglnt;/*===========......
  • 2020 CSP-J
    P7071优秀的拆分(语法)题意给定一个正整数,输出二进制拆分。如果这个数是奇数输出-1。数据规模与约定对于\(100\%\)的数据,\(1\len\le10^7\)。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/......
  • 2021 CSP-J
    P7909分糖果(数学)题意给定\(n,l,r\),求一个数\(x\),当\(l\lex\ler\)时,最大的\(x\bmodn\)。数据规模与约定对于\(100\%\)的数据,\(1\len\lel\ler\le10^9\)。题解假设\(l=K_l*n+R_l,r=K_r*n+R_r,x=K_x*n+R_x\)。我们要求\(R_x\)尽......
  • 2019 CSP-J
    P5660数字游戏(语法)题意给定一个长度最大为\(8\)的01字符串,求字符串中有多少个\(1\)。题解#include<bits/stdc++.h>usingnamespacestd;/*====================*/#defineendl"\n"/*====================*/typedeflonglonglnt;/*====================*/voidSo......
  • 2023 CSP-J
    P9748小苹果(模拟)题意\(n\)个苹果从左到右排成一列,编号为从\(1\)到\(n\)。每天从左侧第\(1\)个苹果开始,每隔\(2\)个苹果拿走\(1\)个苹果。求出多少天能拿完所有的苹果,编号为\(n\)的苹果是在第几天被拿走。数据规模与约定对于\(100\%\)的数据,\(1\len\le10^9......
  • 2022 CSP-J
    P8813乘方(数学,模拟)题意给定两个数\(a,b\),如果\(a^b\le10^9\),输出\(a^b\)的值。否则输出\(-1\)。数据规模与约定对于\(100\%\)的数据,\(1\lea,b\le10^9\)。题解记得开longlong。如果\(a=1\),那么无论\(b\)是多少结果都是\(1\)。如果\(a\ne1\),那么\(a......