dengch

 

Atcoder318

A

思路:直接按题意模拟即可

#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <map>
#include <set>

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;



int main(){
	
	int n,m,p;
	cin >> n >> m >> p;

	if(n < m){
		puts("0");
		return 0;
	}
	int res = 1;
	n -= m;
	res += n / p;

	cout << res << endl;

	return 0;
}

B

思路:很容易可以看出来是一个二维差分的题目,但我没注意这是方格,还是按照矩阵的写法。没能ac,唉

#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <map>
#include <set>

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;

const int N = 110;
int s[N][N];
int n;

int main(){
	cin >> n;

	for(int i = 0; i < n; i ++){
		int a,b,c,d;
		cin >> a >> b >> c >> d;

		a++,b++,c++,d++;
		s[a][c]++;
		s[a][d]--;
		s[b][c]--;
		s[b][d]++;
	}

	for(int i = 1; i < N; i ++)
		for(int j = 1; j < N; j ++)
			s[i][j] += s[i - 1][j] + s[i][j - 1] - s[i - 1][j - 1];

	int res = 0;
	for(int i = 1; i < N; i ++)
		for(int j = 1; j < N; j ++)
			if(s[i][j])res++;

	cout << res << endl;

	return 0;
}

C

思路:贪心加前缀和,因为这道题说买了pass-day可以在任意一天使用,所以和顺序无关,先对每天的花费排个序,并做前缀和预处理。再贪心的枚举花费较大的D天,如果买pass-day的钱小于这几天花费的总额,那么肯定是买pass-day更划算,否则选择不买pass-day。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <map>
#include <set>

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;
const int N = 200010;
vector<int>v[N];
int ans;
int f[N];
LL s[N];

int main(){

	int n,d,p;
	cin >> n >> d >> p;

	for(int i = 1; i <= n; i ++)scanf("%d",&f[i]);

	sort(f + 1,f + n + 1);
	for(int i = 1; i <= n; i ++)s[i] = (LL)s[i - 1] + f[i];
	LL res = 0;
	for(int i = n; i >= 1; i --){
		int l = max(0,i - d);
		if(s[i] - s[l] >= p){
			res = (LL)res + p;
			i -= d;
			i += 1;
		}else{
			res = (LL)res + f[i];
		}
	}


	cout << res << endl;
	return 0;
}

D

思路:直接用dfs搜索即可。细节:当n为奇数时,必定有一个点不能和其他点进行匹配,我们可以选择跳过该点。枚举量为:当前枚举的点的编号,边权和,是否可以跳过该点。当n为偶数时,则不需要考虑是否有点会被跳过。参考自他人代码。

#include <iostream>
#include <algorithm>
#include <cstring>
#include <set>
#include <vector>
#include <map>
#include <set>

using namespace std;

typedef long long LL;
typedef pair<int,int>PII;

const int N = 20;

int v[N][N];
LL ans = -1;
int n;
bool st[N];

void dfs(int u,LL res,bool skip){
//一种枚举结果,更新答案
	if(u > n){
		ans = max(res,ans);
		return;
	}
//如果当前点被枚举过,则直接跳过
	if(st[u]){
		dfs(u + 1,res,skip);
		return;
	}
//如果当前点可以跳过,那么先选择跳过
	if(skip){
		dfs(u + 1,res,0);
	}
	for(int i = u + 1; i <= n; i ++){
		auto t = v[u][i];
		if(!st[i]){
			st[i] = true;
			res = (LL)res + t;
			dfs(u + 1,res,skip);
			st[i] = false;
			res = (LL)res - t;
		}
	}
}


int main(){

	cin >> n;
	for(int i = 1; i < n; i ++)
		for(int j = i + 1; j <= n; j ++){
			int x;
			cin >> x;
			v[i][j] = x;
		}
	LL res = 0;
	dfs(1,res,n % 2);

	cout << ans << endl;
	
	return 0;
}

E

思路:简单的做法就是直接按顺序枚举每个数,枚举的同时查看它之前出现过的位置,答案就加上i(当前枚举的位置) - j(之前出现过的位置) - 1 - cnt(i,j之间相同数的数量)。但如果直接这样枚举的话,会有几个数据超时。我们可以做些优化:维护所有之前出现位置的和sum以及该数出现的数量cnt,更新答案时,就不需要遍历,可以做到O(n)的时间复杂度。

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

//#define x first 
//#define  y second
using namespace std;

typedef long long LL;
typedef pair<LL,LL>PLL;
const int N = 300010;

// struct p{
// 	LL sum;
// 	int cnt;
// };
vector<PLL>v[N];

int n;
int a[N];

int main(){
	cin >> n;

	for(int i = 0; i < n; i ++)scanf("%d",&a[i]);

	LL res = 0;
	for(int i = 0; i < n; i ++){
		int t = a[i];
		int m = v[t].size();
		if(!m){
			v[t].push_back({(LL)i,0ll});
		}else{
			auto x = v[t][m - 1];
			res = (LL)res + (LL)m * i - x.first - m - x.second;
			x.first = (LL)x.first + i;
			x.second = (LL)x.second + m;
			v[t].push_back(x);
		}
	}


	cout << res << endl;
	
	return 0;
}

posted on 2023-09-04 17:42  BkDench  阅读(13)  评论(0)    收藏  举报

导航