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;
}
浙公网安备 33010602011771号