2022年多校冲刺NOIP联训测试6
又双叒叕垫底
A. Start
大模拟,搞心态啊
考场打出来,因为负数下取整的问题挂了\(55\)
可恶
愿世上再无大模拟,愿大模拟不考细节
code
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
#define PASS 1
#define TURN 2
#define DOUBLE 3
#define C2 4
#define A99 5
#define A49 6
#define A19 7
#define A9 8
#define A5 9
#define A2 10
#define A1 11
#define B19 12
#define B9 13
#define B1 14
#define D2 15
#define E99 16
#define E49 17
#define E0 18
int id(){
string card;
cin >> card;
if(card == "PASS")return 1;
if(card == "TURN")return 2;
if(card == "DOUBLE")return 3;
if(card == "C2")return 4;
if(card == "A99")return 5;
if(card == "A49")return 6;
if(card == "A19")return 7;
if(card == "A9")return 8;
if(card == "A5")return 9;
if(card == "A2")return 10;
if(card == "A1")return 11;
if(card == "B19")return 12;
if(card == "B9")return 13;
if(card == "B1")return 14;
if(card == "D2")return 15;
if(card == "E99")return 16;
if(card == "E49")return 17;
if(card == "E0")return 18;
return 999;
}
int n, m ,k, pd[300005], top, p, now, turn, db;
struct gamer{
string name;
int cnt[23];
void init(){
cin >> name;
for(int i = 1; i <= 3; ++i)++cnt[id()];
}
void lose(){memset(cnt,0,sizeof(cnt));}
}a[36];
void mp(){if(top < k){++top;++a[now].cnt[pd[top]];}}
void print(int who, int typ){
cout << a[who].name << " used ";
if(typ == 1)cout << "PASS";
if(typ == 2)cout << "TURN";
if(typ == 3)cout << "DOUBLE";
if(typ == 4)cout << "C2";
if(typ == 5)cout << "A99";
if(typ == 6)cout << "A49";
if(typ == 7)cout << "A19";
if(typ == 8)cout << "A9";
if(typ == 9)cout << "A5";
if(typ == 10)cout << "A2";
if(typ == 11)cout << "A1";
if(typ == 12)cout << "B19";
if(typ == 13)cout << "B9";
if(typ == 14)cout << "B1";
if(typ == 15)cout << "D2";
if(typ == 16)cout << "E99";
if(typ == 17)cout << "E49";
if(typ == 18)cout << "E0";
cout << ",now p=" << p <<".\n";
}
int tp(){
if(a[now].cnt[PASS]){
--a[now].cnt[PASS];
print(now,PASS);
return PASS;
}
if(a[now].cnt[TURN]){
--a[now].cnt[TURN];
print(now,TURN);
turn = -turn;
return TURN;
}
if(a[now].cnt[DOUBLE]){
--a[now].cnt[DOUBLE];
print(now,DOUBLE);
db = 1;
return DOUBLE;
}
return 0;
}
int dbpt(){
int dp = p,bd = 0;
if(a[now].cnt[D2] && floor(p * 0.5) <= 99){bd = D2;dp = floor(p * 0.5);}
int jp = p,bj = 0;
if(a[now].cnt[B19]){jp -= 19; bj = B19;}
else if(a[now].cnt[B9]){jp -= 9; bj = B9;}
else if(a[now].cnt[B1]){jp -= 1; bj = B1;}
int ap = p,bp = 0;
if(a[now].cnt[A1]){ap += 1;bp = A1;}
else if(a[now].cnt[A2]){ap += 2;bp = A2;}
else if(a[now].cnt[A5]){ap += 5;bp = A5;}
else if(a[now].cnt[A9]){ap += 9;bp = A9;}
else if(a[now].cnt[A19]){ap += 19;bp = A19;}
else if(a[now].cnt[A49]){ap += 49;bp = A49;}
else if(a[now].cnt[A99]){ap += 99;bp = A99;}
int cp = p, cb = 0;
if(a[now].cnt[C2]){cp += cp;cb = C2;}
int ep = p, eb = 0;
if(a[now].cnt[E0]){ep = 0; eb = E0;}
else if(a[now].cnt[E49]){ep = 49; eb = E49;}
else if(a[now].cnt[E99]){ep = 99; eb = E99;}
int op = 999999, typ = 0;
if(bd && dp < op){op = dp; typ = bd;}
if(bj && jp < op){op = jp; typ = bj;}
if(bp && ap < op){op = ap; typ = bp;}
if(cb && cp < op){op = cp; typ = cb;}
if(eb && ep < op){op = ep; typ = eb;}
if(op > 99)return 0;
p = op; print(now,typ); --a[now].cnt[typ];
return typ;
}
int pt(){
int cp = p, cb = 0;
if(a[now].cnt[C2] && cp + cp <= 99){cp += cp;cb = C2;}
int ap = p,bp = 0;
if(a[now].cnt[A99] && p + 99 <= 99){ap += 99;bp = A99;}
else if(a[now].cnt[A49] && p + 49 <= 99){ap += 49;bp = A49;}
else if(a[now].cnt[A19] && p + 19 <= 99){ap += 19;bp = A19;}
else if(a[now].cnt[A9] && p + 9 <= 99){ap += 9;bp = A9;}
else if(a[now].cnt[A5] && p + 5 <= 99){ap += 5;bp = A5;}
else if(a[now].cnt[A2] && p + 2 <= 99){ap += 2;bp = A2;}
else if(a[now].cnt[A1] && p + 1 <= 99){ap += 1;bp = A1;}
int jp = p,bj = 0;
if(a[now].cnt[B1] && p - 1 <= 99){jp -= 1; bj = B1;}
else if(a[now].cnt[B9] && p - 9 <= 99){jp -= 9; bj = B9;}
else if(a[now].cnt[B19] && p - 19 <= 99){jp -= 19; bj = B19;}
int dp = p,bd = 0;
if(a[now].cnt[D2] && floor(p * 0.5) <= 99){bd = D2;dp = floor(p * 0.5);}
int ep = p, eb = 0;
if(a[now].cnt[E99]){ep = 99; eb = E99;}
else if(a[now].cnt[E49]){ep = 49; eb = E49;}
else if(a[now].cnt[E0]){ep = 0; eb = E0;}
int op = -999999, typ = 0;
if(cb && cp > op){op = cp; typ = cb;}
if(bp && ap > op){op = ap; typ = bp;}
if(bj && jp > op){op = jp; typ = bj;}
if(bd && dp > op){op = dp; typ = bd;}
if(eb && ep > op){op = ep; typ = eb;}
if(op > 99 || op == -999999)return 0;
p = op; print(now,typ); --a[now].cnt[typ];
return typ;
}
int work(){
if(db){
if(tp()){mp();return 1;}
db = 0;
if(dbpt() == 0)return 0;
mp();
}
if(pt() == 0){
if(tp() == 0)return 0;
}
mp();
return 1;
}
int main(){
ios::sync_with_stdio(false);
cin >> n >> m >> k;
for(int i = 1; i <= n; ++i)a[i].init();
for(int i = 1; i <= k; ++i)pd[i] = id();
top = 0; now = 1;
for(int i = 1; i <= m; ++i){
cout << "Round " << i << ":\n";
turn = 1; db = 0; p = 0;
while(work()){
now += turn;
if(now > n)now = 1;
if(now == 0)now = n;
}
cout << a[now].name << " lost the game.\n";
a[now].lose();mp();mp();mp();
}
return 0;
}
B. Dream
人傻了,人傻了,这是全场最水的题居然没有看出来,因为读题少看一句话
保证每种字母恰好有\(n\)个
可恶啊。。。
正解可以输出\(n\)个\(g\)再输出\(n\)个\(z\),再输出\(1\)个\(g\)
一定存在这种方案,考虑第\(n\)个和第\(2n\)个\(g\)之间有一个完整的\(2*n\)的序列,其中必然有\(n\)个\(z\)
code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int main(){
scanf("%d",&n);
for(int i = 1; i <= n; ++i)putchar('g');
for(int i = 1; i <= n; ++i)putchar('z');
putchar('g');
return 0;
}
C. It
考场唯一切掉的题,确实很水,不过我是\(nlogn\)的
人傻复杂度大
排序后考虑相邻的同种元素,把他们赋值成两边的答案较大值 + 1即可
code
#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
inline int read(){
int x = 0; char c = getchar();
while(c > '9' || c < '0')c = getchar();
do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while (c >='0'&&c <='9');
return x;
}
const int maxn = 1e6 + 55;
int a[maxn],p[maxn], n, ans[maxn];
bool cmp(int x,int y){return a[x] == a[y] ? x < y : a[x] < a[y];}
int main(){
n = read();
for(int i = 1; i <= n; ++i)a[i] = read() + 1;
for(int i = 1; i <= n; ++i)p[i] = i;
sort(p + 1, p + n + 1, cmp);
for(int i = 1; i <= n; ++i){
int j = i;
while(p[j + 1] == p[j] + 1 && a[p[j + 1]] == a[p[i]] && j <= n) ++j;
int now = 1 + max(ans[p[i] - 1], ans[p[j] + 1]);
for(int k = i; k <= j; ++k)ans[p[k]] = now;
i = j;
}
for(int i = 1; i <= n; ++i)printf("%d ",ans[i]);
return 0;
}
D. Possible
深度有限这个条件非常有用,考虑两点距离,因为只有返祖边,我们可以枚举中间点,然后就是中间点到两边的点距离和的最小值
预处理每个深度的点到其子树所有点的最短路
均摊复杂度\(nlogn\)
code
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
inline int read(){
int x = 0; char c = getchar();
while(c > '9' || c < '0')c = getchar();
do{x = (x << 3) + (x << 1) + (c ^ 48); c = getchar();}while (c >='0'&&c <='9');
return x;
}
typedef long long ll;
typedef pair<ll,int> pli;
const int maxn = 100005;
const int maxm = 500005;
int n,m,q,tot,head[maxn];
struct edge{
int to,net,val;
}e[maxm << 1 | 1];
void add(int u,int v,int w){
e[++tot].net = head[u];
head[u] = tot;
e[tot].to = v;
e[tot].val = w;
};
bool vis[maxn];
priority_queue<pli, vector<pli>, greater<pli> >Q;
ll dis[27][maxn];
void dij(int now, int dp){
Q.push(make_pair(0,now));
dis[dp][now] = 0;
while(!Q.empty()){
pair<ll, int> y = Q.top(); Q.pop();
int x = y.second;
if(dis[dp][x] < y.first)continue;
for(int i = head[x];i;i=e[i].net){
int v = e[i].to;
if(!vis[v])continue;
if(dis[dp][v] > dis[dp][x] + e[i].val){
dis[dp][v] = dis[dp][x] + e[i].val;
Q.push(make_pair(dis[dp][v],v));
}
}
}
}
int fa[maxn], dep[maxn];
void dfs1(int x){
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(dep[v])continue;
dep[v] = dep[x] + 1;
fa[v] = x;
dfs1(v);
}
}
void dfs2(int x){
for(int i = head[x]; i; i = e[i].net){
int v = e[i].to;
if(fa[v] == x && !vis[v])dfs2(v);
}
vis[x] = 1;
dij(x, dep[x]);
}
void query(){
int u = read(), v = read();
int x = u, y = v;
while(dep[x] > dep[y]) x = fa[x];
while(dep[x] < dep[y]) y = fa[y];
while(x != y)x = fa[x], y = fa[y];
ll ans = 0x3f3f3f3f3f3f3f3f;
for(int i = 1; i <= dep[x]; ++i)ans = min(ans, dis[i][u] + dis[i][v]);
printf("%lld\n",ans);
}
int main(){
n = read(); m = read(); q = read();
for(int i = 1; i < n; ++i){
int u = read(), v = read(), w = read();
add(u, v, w);add(v, u, w);
}
memset(dis,0x3f,sizeof(dis));
dep[1] = 1; dfs1(1);
for(int i = n;i <= m; ++i){
int u = read(), v = read(), w = read();
add(u, v, w);add(v, u, w);
}
dfs2(1);
for(int i = 1; i <= q; ++i)query();
return 0;
}