The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou)

The 2023 ICPC Asia Hangzhou Regional Contest (The 2nd Universal Cup. Stage 22: Hangzhou)

M. V-Diagram

题意:给定一个“v图”,求平均值最大的子"v图"

思路:原图的最低点以及左右两个点必须取,如何先取满左边或者右边在贪心即可

void solve(){
    ll n;
    cin >> n;
    vector<ll> a(n + 1);
    for(int i = 1; i <= n; i ++) cin >> a[i];
    ll idx = -1;
    for(int i = 2; i < n; i ++){
        if(a[i] < a[i - 1] && a[i] < a[i + 1]){
            idx = i;
            break;
        }
    }
    ld sum1 = 0, sum2 = 0;
    ld ans1 = 0, ans2 = 0;
    for(int i = 1; i <= n; i ++){
        sum1 += a[i];
        if(i >= idx + 1){
            ans1 = max(ans1, sum1 / i);
        }
    }
    for(int i = n; i >= 1; i --){
        sum2 += a[i];
        if(i <= idx - 1){
            ans2 = max(ans2, sum2 / (n - i + 1));
        }
    }
    cout << fixed << setprecision(20) << max(ans1, ans2) << '\n';
}

J. Mysterious Tree

题意:给定一颗树,要不是链,要不是菊花图, 要求在⌈n / 2⌉ + 3次询问出是链还是菊花图,每次可以询问两条边是否存在边

思路:以两个相邻元素为一组询问一次,如果是奇数点数那就把 1 和 n 两个点再问一次,如果都不存在边,那么一定不是菊花图,然后记录两个相邻点为 u 和 v,任选两个非 u v 的点 p[0] 和 p[1] ,先询问 u 和 p[0] ,如果存在再问 v 和 p[1],如果也存在必定是菊花图,如果 u 和 p[0] 不存在,再用 p[1] 询问两次即可,总之就是菊花图必定至少存在一个度数为 3 的点

ll ask(ll x, ll y){
    cout << "? " << x << ' ' << y << endl;
    ll ans;
    cin >> ans;
    return ans;
}
 
void solve(){
    ll n;
    cin >> n;
    bool ok = 0;
    ll u = 0, v = 0;
    for(int i = 2; i <= n; i += 2){
        ll res = ask(i - 1, i);
        if(res){
            ok = 1;
            u = i - 1;
            v = i;
        }
    }
    if(n & 1){
        ll res = ask(1, n);
        if(res){
            ok = 1;
            u = 1;
            v = n;
        } 
    }
    if(!ok){
        cout << "! " << 1 << endl;
        return;
    }
    
    vector<ll> p;
    for(int i = 1; i <= n; i ++){
        if(i != u && i != v){
            p.push_back(i);
            if(p.size() == 2) break;
        }
    }
    if(ask(u, p[0])){
        ll res = ask(u, p[1]);
        if(res) cout << "! " << 2 << endl;
        else cout << "! " << 1 << endl;
    }
    else{
        ll res = ask(v, p[0]) + ask(v, p[1]);
        if(res == 2) cout << "! " << 2 << endl;
        else cout << "! " << 1 << endl; 
    }
}

D. Operator Precedence

题意:对给定的两种符号运算构造出一种两者相等的情况

思路:对第二个式子括号中的数字分别赋值 2 和 -1 然后推出首相和尾项的通项

void solve(){
    ll n;
    cin >> n;
    n *= 2;
    vector<ll> a(n + 1);
    for(int i = 2; i < n; i ++){
        if(i % 2 == 0) a[i] = -1;
        else a[i] = 2;
    }
    a[1] = 1;
    a[n] = n - 3;
 
    auto check =[&]() -> bool{
        ll res1 = 0, res2 = 1;
        for(int i = 1; i < n; i += 2){
            res1 = (res1 + (a[i] * a[i + 1]));
        }
        res2 *= a[1] * a[n];
        for(int i = 2; i < n; i += 2){
            res2 = (res2 * (a[i] + a[i + 1]));
        }
        if(res1 == res2 && res1 != 0){
            return true;
        }    
        return false;
    };
    // cout << check() << '\n';
    for(int i = 1; i <= n; i ++) cout << a[i] << ' ';
    cout << '\n';
}

G. Snake Move

题意:给定一个地图,存在一只贪吃蛇,求蛇头到每个点的距离的平方的和

思路:BFS即可,蛇身要对 k - i + 1 取 max

typedef array<ll, 3> ar;
ll dx[] = {1, -1, 0, 0}, dy[] = {0, 0, 1, -1};

ll n, m, k, bx, by;
char g[N][N];
ll dis[N][N];
bool vis[N][N];

void solve(){
    cin >> n >> m >> k;
    for(int i = 1; i <= k; i ++){
        ll x, y;
        cin >> x >> y;
        if(i == 1){
            bx = x;
            by = y;
        }
        dis[x][y] = k - i + 1;
    }
    for(int i = 1; i <= n; i ++){
        for(int j = 1; j <= m; j ++){
            cin >> g[i][j];
        }
    }
    ull ans = 0;
    priority_queue<ar, vector<ar>, greater<ar>> q;
    q.push({0, bx, by});
    vis[bx][by] = 1;
    while(!q.empty()){
        auto [d, x, y] = q.top();
        q.pop();
        ans += ull(d) * d;
        for(ll i = 0; i < 4; i ++){
            ll x1 = x + dx[i], y1 = y + dy[i];
            if(x1 > n || x1 < 1 || y1 > m || y1 < 1 || g[x1][y1] == '#') continue;
            if(!vis[x1][y1]){
                q.push({max(dis[x1][y1], d + 1), x1, y1});
                vis[x1][y1] = 1;
            }
        }
    }
    cout << ans << '\n';
}
H. Sugar Sweet II
题意:给定 n 个人,每个人初始有 a[i] 包糖果,存在 n 个事件,每个事件的描述如下:对于第 i 个人,如果它的糖果数量小于第 b[i] 个人,那么他获得 w[i] 包糖果,这 n 个事件是均等概率的随机发生,求最后每个人的糖果数量的期望值
思路:对于给定的每一对有三种情况:
(1): a[i] < a[b[i]]:这种情况下事件 i 必定发生
(2): a[b[i]] + w[b[i]] <= a[i]:这种情况下该事件必定不发生
(3): a[b[i]] + w[b[i]] > a[i]:该事件只有当事件 b[i] 发生之后才会发生
所以对第三种情况,令 b[i] 向 i 连边,然后从所有的必定发生的事件向第三种情况做 dfs,对于每个第三种情况,就是它距离本身最近的那个必定发生的父亲事件的距离的全排列分之一的概率发生
ll fac[N], inv[N];
 
ll fastpow(ll a, ll n){
    ll base = a, res = 1;
    while(n){
        if(n & 1) res = (res * base) % mod;
        base = (base * base) % mod;
        n >>= 1;
    }
    return res;
}
 
ll Inv(ll a){
    return fastpow(a, mod - 2);
}
 
ll C(ll n, ll m){
    if(n < 0 || m < 0 || n < m) return 0;
    return fac[n] * inv[m] % mod * inv[n - m] % mod;
}
 
void init(ll n){
    fac[0] = 1;
    for(int i = 1; i <= n; i ++) fac[i] = (i * fac[i - 1]) % mod;
    inv[n] = Inv(fac[n]);
    for(int i = n - 1; i >= 0; i --) inv[i] = inv[i + 1] * (i + 1) % mod;
}
 
vector<ll> edge[N];
ll dis[N];
 
void dfs(ll x){
    for(auto v : edge[x]){
        dis[v] = dis[x] + 1;
        dfs(v);
    }
}
 
void solve(){
    ll n;
    cin >> n;
    vector<ll> a(n + 1), b(n + 1), w(n + 1), vec;
    for(int i = 1; i <= n; i ++) cin >> a[i];
    for(int i = 1; i <= n; i ++) cin >> b[i];
    for(int i = 1; i <= n; i ++) cin >> w[i];
    for(int i = 1; i <= n; i ++) dis[i] = 0, edge[i].clear();
    for(int i = 1; i <= n; i ++){
        int j = b[i];
        if(a[i] < a[j]) dis[i] = 1, vec.push_back(i);//必然发生
        else if(a[j] + w[j] <= a[i]) dis[i] = 0;//必然不发生
        else edge[j].push_back(i);
    }
    for(auto x : vec){
        dfs(x);
    }
    for(int i = 1; i <= n; i ++){
        if(dis[i] == 0){
            cout << a[i] << ' ';
            continue;
        }
        ll ans = (a[i] + w[i] * inv[dis[i] % mod]) % mod;
        cout << ans << ' ';
    }
    cout << '\n';
}
 
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0);cout.tie(0);
    init(500000);
    int t = 1;
    cin >> t;
    while(t --){
        solve();
    }
    return 0;
}

 

posted @ 2024-10-09 20:01  Rosmontis_L  阅读(120)  评论(0)    收藏  举报