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;
}
posted @ 2022-07-26 22:05  Chen_jr  阅读(40)  评论(1编辑  收藏  举报