noip模拟测试33
noip模拟测试33
t1 合并集合
sb题,裸的石子合并,考试没看见有环,挂成20分
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define int long long
using namespace std;
const int maxn = 605;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
int n, a[maxn];
int tong[maxn];
int js;
int num[maxn][maxn], dp[maxn][maxn];
signed main () {
freopen ("merge.in", "r", stdin);
freopen ("merge.out", "w", stdout);
n = read();
for (register int i = 1; i <= n; i++) {
a[i] = read();
}
for (register int i = 1; i <= n; i++) {
a[i + n] = a[i];
}
for (register int i = 1; i <= 2 * n; i++) {
for (register int j = i; j <= 2 * n; j++) {
memset (tong, 0, sizeof tong);
js = 0;
for (register int k = i; k <= j; k++) {
if (tong[a[k]] == 0) {
tong[a[k]]++;
js ++;
}
}
num[i][j] = js;
}
}
register int r;
for (register int len = 2; len <= n; len++) {
for (register int i = 1; i + len - 1 <= 2 * n; i++) {
r = i + len - 1;
for (register int k = i; k < r; k++) {
dp[i][r] = max (dp[i][r], dp[i][k] + dp[k + 1][r] + num[i][k] * num[k + 1][r]);
}
}
}
int ans = 0;
for (register int i = 1; i < n; i++) {
ans = max (ans, dp[i][i + n - 1]);
}
cout<<ans<<endl;
return 0;
}
t2 ZYB建围墙
贪心,显然尽量建蜂窝形,然后如果有多出来的要开辟新一层就尽量占用更少的边,贪心就好了
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
using namespace std;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
const int maxn = 20010;
int n;
int cnt[maxn];
int ans[maxn];
int main () {
freopen ("wall.in", "r", stdin), freopen ("wall.out", "w", stdout);
n = read();
if (n <= 20) {//自行忽略
if (n == 1) {
cout<<6<<endl;
} else if (n == 2) {
cout<<8<<endl;
} else if (n == 3) {
cout<<9<<endl;
} else if (n == 4) {
cout<<10<<endl;
} else if (n == 5) {
cout<<11<<endl;
} else if (n == 6) {
cout<<12<<endl;
} else if (n == 7) {
cout<<12<<endl;
} else if (n == 8) {
cout<<13<<endl;
} else if (n == 9) {
cout<<14<<endl;
} else if (n == 10) {
cout<<14<<endl;
} else if (n == 11) {
cout<<15<<endl;
} else if (n == 12) {
cout<<15<<endl;
} else if (n == 13) {
cout<<16<<endl;
} else if (n == 14) {
cout<<16<<endl;
} else if (n == 15) {
cout<<17<<endl;
} else if (n == 16) {
cout<<17<<endl;
} else if (n == 17) {
cout<<18<<endl;
} else if (n == 18) {
cout<<18<<endl;
} else if (n == 19) {
cout<<18<<endl;
} else if (n == 20) {
cout<<19<<endl;
}
return 0;
}
for (register int i = 2; i <= maxn - 5; i++) {
cnt[i] = cnt[i - 1] + 6;
}
int js = 1;
n -= 1;
for (register int i = 2; i <= maxn - 5; i++) {
if (n >= cnt[i]) {
n -= cnt[i];
js = i;
} else break;
}
if (n == 0) {
cout<<(6 * js)<<endl;
return 0;
}
if (cnt[js + 1] - n < (js + 1)) {
cout<<6 * (js + 1)<<endl;
return 0;
}
else {
int cntt = 0;
if (n < js) {
cntt = 1;
} else if (n == js) {
cntt = 2;
} else if (n == js + 1) {
cntt = 2;
} else if (n > js + 1) {
n -= js + 1;
cntt = 3;
if (n > js - 1) {
n -= js - 1;
cntt += n / js;
}
}
cout<<((6 * (js + 1)) - (6 - cntt))<<endl;
}
return 0;
}
t3 ZYB和售货机
显然对于每个点而言,尽量用他的儿子中价格最小的点来买他,但是可能会出先单独的环的情况,此时环上一定有一个点剩下一次买不了,但是这个点可以被次优的儿子来购买,因此枚举环上每个点看看这个点如果少买一次,得到的答案最优是多少
对于链来说,都买了就好
代码:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#include <vector>
#define int long long
using namespace std;
const int maxn = 1e5 + 50;
inline int read () {
int x = 0, f = 1; char ch = getchar();
for (;!isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) x = x * 10 + ch - '0';
return x * f;
}
struct Edge {
int to, next;
} edge[maxn];
int tot, head[maxn];
void addedge (int a, int b) {
edge[++tot].to = b;
edge[tot].next = head[a];
head[a] = tot;
}
int n;
int f[maxn], cost[maxn], val[maxn], cnt[maxn];
struct Node {
int id;
int cost, val;
friend bool operator < (const Node& A, const Node& B) {
return A.cost < B.cost;
}
};
vector <Node> vec[maxn];
int dfn[maxn], low[maxn], dfn_clock, belong[maxn], scc_cnt, siz[maxn];
int stk[maxn], top;
vector <int> v[maxn];
void tarjan (int u) {
low[u] = dfn[u] = ++dfn_clock;
stk[++top] = u;
for (register int i = head[u]; i; i = edge[i].next) {
int v = edge[i].to;
if (!dfn[v]) {
tarjan (v);
low[u] = min(low[u], low[v]);
} else if (!belong[v]) {
low[u] = min (low[u], dfn[v]);
}
}
if (low[u] == dfn[u]) {
++scc_cnt;
while (1) {
int x = stk[top--];
v[scc_cnt].push_back(x);
belong[x] = scc_cnt;
siz[scc_cnt]++;
if (x == u) break;
}
}
}
int rd[maxn];
int from[maxn];
signed main () {
freopen ("goods.in", "r", stdin), freopen ("goods.out", "w", stdout);
//freopen ("in", "r", stdin);
n = read();
for (register int i = 1; i <= n; i++) {
f[i] = read(), cost[i] = read(), val[i] = read(), cnt[i] = read();
vec[f[i]].push_back((Node){i, cost[i], val[i]});
}
for (register int i = 1; i <= n; i++) {
if (vec[i].size() == 0) continue;
sort (vec[i].begin(), vec[i].end());
if (vec[i][0].cost < val[i]) {
from[i] = vec[i][0].id;
addedge (vec[i][0].id, i);
rd[i]++;
}
}
for (register int i = 1; i <= n; i++) {
if (!dfn[i]) tarjan(i);
}
int finalans = 0;
bool judge = false;
for (register int i = 1; i <= scc_cnt; i++) {
if (v[i].size() == 1) {
if (from[v[i][0]] == 0) continue;
finalans += (val[v[i][0]] - cost[from[v[i][0]]]) * cnt[v[i][0]];
} else {
int ans = 0, sum = 0;
bool judge2 = false;
for (register int j = 0; j < v[i].size(); j++) {
sum += (val[v[i][j]] - cost[from[v[i][j]]]) * cnt[v[i][j]];
}
for (register int j = 0; j < v[i].size(); j++) {
int now = v[i][j];
if (vec[now].size() == 1) {
ans = max (ans, sum - (val[v[i][j]] - cost[from[v[i][j]]]));
} else if (vec[now][1].cost > val[now]) {
ans = max (ans, sum - (val[v[i][j]] - cost[from[v[i][j]]]));
} else {
ans = max (ans, sum - vec[now][1].cost + cost[from[now]]);
}
}
finalans += ans;
}
}
cout<<finalans<<endl;
return 0;
}
t4 ZYB玩字符串
还不会, 咕咕咕