昨天不在状态直接摸鱼到200+了。
题解包括abc题,d题因为难度太大本人没码出来。
由于题目是中文题所以题解不会有题目简述
虽然bc题题意相同数据量不同,笔者还是会提供不同的思路。
显然就是不断把最大的变成次大的过程,
首先用s/p算出最多能减少的kg数。
然后排序从大到小把第i个的重量变成第i+1个的重量。
如果所有车都变成同一重量(也就是变成最小那辆车的重量)在判断能不能把所有的车都变成重量为1就行了
不能的话就总体减去剩余的 可减次数/n。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
LL num[maxn];
bool cmp(LL a, LL b) {
return a > b;
}
int main() {
int n;
while (~scanf("%d", &n)) {
for (int i = 0; i < n; i++)
scanf("%lld", &num[i]);
sort(num, num + n,cmp);
LL p, s;
scanf("%lld%lld", &p, &s);
LL cnt = s / p;
LL ans = num[0], t = 1;
for (int i = 1; i < n; i++) {
if ((num[i-1] - num[i])*t <= cnt) {
ans = num[i];
cnt -= (num[i - 1] - num[i])*t;
t++;
}
else break;
}
if (cnt > 0)
ans -= cnt / t;
if (ans <= 0) ans = 1;
printf("%lld\n", ans);
}
return 0;
}
因为n只有20,那么把图建出来之后直接暴力就行了。
这里注意一点就是需要建立映射函数保证1操作下的建图正确性
暴力要注意的是对每一点进行dfs
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e4 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
map<int, int>mp;
vector<int>edge[100];
LL val[100];
LL tmp;
bool vis[100];
void dfs(int u) {
tmp += val[u];
vis[u] = 1;
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
if (vis[v]) continue;
dfs(v);
}
}
int main() {
int n;
while (~scanf("%d", &n)) {
mp.clear();
for (int i = 0; i < 100; i++)
edge[i].clear();
for (int i = 1; i <= n; i++) {
scanf("%lld", &val[i]);
mp[i] = i;
}
int q, op, l, r, x;
LL y;
scanf("%d", &q);
while (q--) {
scanf("%d", &op);
if (op == 0) {
scanf("%d%lld", &x,&y);
n++;
val[n] = y;
mp[x] = n;
}
else {
scanf("%d%d%d", &x, &l, &r);
for (int i = l; i <= r; i++) {
edge[mp[x]].push_back(mp[i]);
}
}
}
LL ans = INF;
for (int i = 1; i <= n; i++) {
memset(vis, 0, sizeof(vis));
tmp = 0;
dfs(i);
ans = min(tmp, ans);
}
printf("%lld\n", ans);
}
return 0;
}
数据量变大了显然不能再暴力。
根据上一题的经验可知,如果我们对图进行缩点的话,我们要的结果一定在出度为0的点中。
所以先对图强连通缩点然后枚举出度为0的点找出最小值就行了。
建图方式跟前一题是一样的。
#include<iostream>
#include<string>
#include<cstring>
#include<vector>
#include<map>
#include<algorithm>
#include<queue>
#include<set>
#include<cstdio>
#include<functional>
#include<iomanip>
#include<cmath>
#include<stack>
#include<iomanip>
#include<functional>
#include <iomanip>
using namespace std;
typedef long long LL;
typedef unsigned long long ull;
const int maxn = 2*(int)1e5 + 10;
const int BN = 30;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3f;
const int mod = 1000000007;
const double eps = 1e-6;
const double PI = acos(-1);
map<int, int>mp;
LL vals[maxn];
struct tarjan {
int dfn[maxn];//该节点被搜索的次序(时间戳)
int low[maxn];//为i或i的子树能够追溯到的最早的栈中节点的次序号
int stk[maxn];//栈模拟数组
int col[maxn];//强联通分量染色
int in[maxn], out[maxn];//入度出度
bool vis[maxn];//是否在栈内
LL val[maxn];
vector<int>edge[maxn];//保存边
int tot, coln, tops, n;//搜索次序,染色总数,栈顶,点数
void init(int _n) {
n = _n;
for (int i = 1; i <maxn; i++) {
dfn[i] = -1;
col[i] = out[i] = low[i] = 0;
edge[i].clear();
}
tot = tops = coln = 0;
}
void dfs(int u) {
dfn[u] = low[u] = ++tot;
stk[++tops] = u;
vis[u] = true;
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
if (dfn[v] == -1) {
dfs(v);
low[u] = min(low[u], low[v]);
}
else if (vis[v])
low[u] = min(low[u], dfn[v]);
}
if (dfn[u] == low[u]) {
int v;
vector<int> ans;
coln++;
do {
v = stk[tops--];
vis[v] = false;
col[v] = coln;
} while (v != u);
}
}
void solve() {
for (int i = 1; i <= n; i++)
if (dfn[i] == -1)
dfs(i);
}
void dag() {
for (int u = 1; u <= n; u++) {
for (int i = 0; i < edge[u].size(); i++) {
int v = edge[u][i];
int x = col[u], y = col[v];
if (x != y) {
out[x]++;
}
}
}
memset(val, 0, sizeof(val));
for (int u = 1; u <= n; u++)
val[col[u]] += vals[u];
LL ans = INF;
for (int u = 1; u <= n; u++) {
if (out[col[u]] == 0) {
ans = min(ans, val[col[u]]);
}
}
printf("%lld\n", ans);
}
}tar;
int main() {
int n;
while (~scanf("%d", &n)) {
tar.init(n);
mp.clear();
for (int i = 1; i <= n; i++) {
scanf("%lld", &vals[i]);
mp[i] = i;
}
int q, op, l, r, x;
LL y;
scanf("%d", &q);
while (q--) {
scanf("%d", &op);
if (op == 0) {
scanf("%d%lld", &x, &y);
n++;
vals[n] = y;
mp[x] = n;
tar.n++;
}
else {
scanf("%d%d%d", &x, &l, &r);
for (int i = l; i <= r; i++) {
tar.edge[mp[x]].push_back(mp[i]);
}
}
}
tar.solve();
tar.dag();
}
return 0;
}
d题因为数据量本身不能建图,所以笔者不会做