首页 > 其他分享 >AtCoder Beginner Contest(abc) 318

AtCoder Beginner Contest(abc) 318

时间:2023-11-06 19:11:06浏览次数:35  
标签:AtCoder abc int res 位置 318 Ax 宝藏 define




B - Overlapping sheets

难度: ⭐

题目大意

在一个坐标系中给出覆盖多个矩形, 问最后所有矩形覆盖的总面积是多少;

解题思路

坐标系的范围不大, 标记后遍历即可; 还是要注意给的是坐标系的点, 计算的是边;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
bool st[110][110];
signed main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int a, b, c, d;
        cin >> a >> b >> c >> d;
        for (int x = a + 1; x <= b; x++) {
            for (int y = c + 1; y <= d; y++) {
                st[x][y] = true;
            }
        }
    }
    for (int i = 1; i <= 100; i++) {
        for (int j = 1; j <= 100; j++) {
            if (st[i][j]) idx++;
        }
    }
    cout << idx;
    return 0;
}




C - Blue Spring

难度: ⭐⭐

题目大意

小莫要在宾馆待n天, 宾馆第i天的住宿费用为fi; 小莫还可以选择宾馆的套餐, 支付p元可以在宾馆住d天, 这d天可以随意分配; 问小莫怎么选择可以支付最少费用;

解题思路

因为套餐的天数可以随意分配, 所以我们可以先把每天的住宿费用从大到小遍历, 然后计算当前的花费的总费用x, 如果遍历到第i个时, x>=p并且天数idx<=d, 那么这些天用套餐度过会更便宜, 决定使用套餐后我们就可以把idx和d之间差的那几天跳过就可, 即从第(i+ d - idx)个看起, 别忘了天数idx和费用x清零;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
int f[N];
signed main() {
    int k;
    cin >> n >> m >> k;
    for (int i = 1; i <= n; i++) {
        cin >> f[i];
    }
    sort(f + 1, f + 1 + n,greater<int>());
    int x = 0, y = 0;
    for (int i = 1; i <= n; i++) {
        x += f[i];
        idx++;
        if (idx <= m && x >= k) {
            i += (m - idx);
            idx = 0;
            x = 0;
            y += k;
        }
    }
    cout << y + x;
    return 0;
}




D - General Weighted Max Matching

难度: ⭐⭐⭐

题目大意

在一个无向有权图中有n个节点, 每两个点之间都有一条带权边, 我们需要从中选出若干条边, 要求是这些边的端点各不相同, 即对于边a-b和c-d: a!=c, a!=d, b!=c, b!=d; 问可以得到的边权值和最大为多少;

解题思路

因为n最大为16, 所以我们可以考虑用状压dp来做, 当然dfs暴搜也能做但是不如状压好写; 状态表示dp[i]表示状态为i的权值和最大为多少, 对于状态i是一个n的二进制, 每一位表示一个节点是否被选择, 也就是说每选择一条边都会有两个点被选择, 也就是二进制的两个位置由0变为1; 并且题目要求每条边的端点各不相同, 所以如果状态i中1的个数是奇数说明该状态不合法; 综上所述, 对于状态转移我们可以从状态i中为1的位置中挑出两个j和k, 说明这次我们选择了j+1和k+1之间的边, 即dp[i] = max(dp[i], dp[i - (1 << j) - (1 << k)] + f[j + 1][k + 1]), 在状态转移的过程中顺便记录最大值就行;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 2e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx;
int f[20][20];
int dp[1 << 17];
signed main() {
    cin >> n;
    int res = 0;
    for (int i = 1; i <= n; i++) {
        for (int j = i + 1; j <= n; j++) {
            cin >> f[i][j];
        }
    }
    for (int i = 1; i < 1 << n; i++) {
        int num = 0;
        for (int j = 0; j < n; j++) {
            if ((i >> j) & 1) num++;
        }
        if (num % 2) continue;
        for (int j = 0; j < n; j++) {
            for (int k = j + 1; k < n; k++) {
                if (((i >> j) & 1) && ((i >> k) & 1)) {
                    int h = i - (1 << j) - (1 << k);
                    dp[i] = max(dp[i], dp[h] + f[j + 1][k + 1]);
                    res = max(res, dp[i]);
                }
            }
        }
    }
    cout << res;
    return 0;
}




E - Sandwiches

难度: ⭐⭐⭐

题目大意

给定一个长度为n的数列Ai, 请问其中有多少个满足条件的三元组(i, j, k);
条件是: Ai = Ak, Ai != Aj;

解题思路

这题可以线性解决, 从头遍历整个数列, 设当前位置是x, 我们用一个数组res[x]表示当三元组中k = x时有多少满足条件的三元组, 很明显k前面必须要有一个Ak相同的数, 所以设p[Ax]表示左边距离第x个数最近的Ax的位置在哪; 通过题目条件我们发现res[x]是可以从res[p[Ax]]继承过来的, res[p[Ax]]是指三元组中k = p[Ax]时有多少种三元组, 我们把k从p[Ax]换成x同样也是合法的三元组; 然后我们再分析之前没有的三元组, 新的三元组无非就是因为从p[Ax]到x之间有(x - p[Ax] - 1)个不为Ak的值, 所以我们可以把k固定为x, j从这(x - p[Ax] - 1)中选, i就可以从x之前所有值为Ax的位置中选, 所以我们再开一个数组f[Ax]表示截止到第x个数之前有多少个值为Ax的数, 所以最后得到计算式: res[x] = res[p[Ax]] + f[Ax] * (x - p[Ax] - 1); 最后再把每个位置上的res[i]加起来即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 3e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, idx, maxn;
int f[N], p[N], res[N];
signed main() {
    cin >> n;
    for (int i = 1; i <= n; i++) {
        int x;
        cin >> x;
        maxn = max(maxn, x);
        if (p[x]) {
            res[i] = res[p[x]] + f[x] * (i - p[x] - 1);
        }
        f[x]++;
        p[x] = i;
    }
    for (int i = 1; i <=n; i++) idx += res[i];
    cout << idx;
    return 0;
}




F - Octopus

难度: ⭐⭐⭐⭐

题目大意

在x轴上有一个章鱼, 章鱼有n个触手, 每个触手的长度为Li; 同时x轴上也有n个宝藏位置为Ni; 章鱼想获得宝藏有两种方式, 一是自己本身就在那个位置, 二是触手可以从够到那个位置; 设章鱼的位置在k, 那么如果k + Ai >= Ni 或者k - Ai <= Ni就说明该触手可以够到该宝藏; 如果章鱼想得到所有宝藏, 请问章鱼的位置k有多少种可以满足;

解题思路

由于本题的位置范围过大, 肯定是不能从每个位置下手, 所以我们要考虑区间; 再次之前我们先考虑如果已经确定了位置k, 我们该如何判定该位置是否合法; 我们可以把所有宝藏到位置k的相对距离Di从小到大排序, 然后把触手长度也从小到大排序, 让他们一一对应, 看是否每个Li都大于等于Di即可; 从上述方法种我们发现对于一个位置k, 他会让每个触手和宝藏实现一一对应的关系, 那么如果移动了k, 但是触手和宝藏之间的对应关系却没有变化, 那么移动后的k肯定也是合法的, 我们继续移动k直到触手和宝藏的对应关系发生了变化, 设最初是k值为l, 最后为r, l到r肯定是一段连续的区间, 这样我们就找到了可以用于计算的区间;
所以现在就是需要确定所有的区间, 那什么时候触手和宝藏的对应关系会发生变化呢, 那就是某个宝藏处于某个触手的边缘位置, 只要章鱼位置再移动一格, 宝藏就会离开触手范围, 对应关系就会发生变化; 那具体哪几个边界是我们所需要的呢, 遍历就可以了, 毕竟题目给的n的范围只有200个; 首先我们把所有上述情况的位置k找到并存在下来, 找的过程无非就是先遍历所有宝藏再遍历所有触手, k的位置就是X[i] + L[j]和X[i] - L[j]; 把这些k从小到大排序后去重就可以哪来确定有效区间了; 我们遍历这些区间(如果有m个区间端点k, 说明就m-1个区间(i和i+1)), 设左端点是l, 右端点是r; k在l时刚好可以够到一个宝藏, k在r时也刚好可以够到一个宝藏; 所以从[l+1, r-1]之间没有位置可以刚好够到一个宝藏, 所以整个区间内对应关系不变, 所以我们只检查l+1这个位置即可, 如果l+1合法, 那么区间[l+1, r-1]内的值都合法; 因为端点l和r是引起对应关系变化的位置, 所以我们最后再检查所有端点即可;

神秘代码

#include<bits/stdc++.h>
#define int long long
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
#define endl '\n'
using namespace std;
const int N = 3e5 + 10, mod = 998244353;
typedef pair<int, int> PII;
int n, m, res;
int X[210], L[210], D[210];
vector<int> v;
bool check(int k) {
    for (int i = 1; i <= n; i++) {
        D[i] = abs(X[i] - k);
    }
    sort(D + 1, D + n + 1);
    bool f = true;
    for (int i = 1; i <= n; i++) {
        if (L[i] < D[i]) {
            return false;
        }
    }
    return true;
}
signed main() {
    cin >> n;
    for (int i = 1; i <= n; i++) cin >> X[i];
    for (int i = 1; i <= n; i++) cin >> L[i];
    sort(L + 1, L + n + 1);
    for (int i = 1; i <= n; i++) {
        for (int j = 1; j <= n; j++) {
            v.push_back(X[i] + L[j]);
            v.push_back(X[i] - L[j]);
        }
    }
    sort(v.begin(), v.end());
    v.erase(unique(v.begin(), v.end()), v.end());
    for (int i = 0; i < v.size() - 1; i++) {
        if (check(v[i] + 1)) res += v[i + 1] - v[i] - 1;
    }
    for (int i = 0; i < v.size(); i++) {
        if (check(v[i])) res++;
    }
    cout << res;
    return 0;
}

标签:AtCoder,abc,int,res,位置,318,Ax,宝藏,define
From: https://www.cnblogs.com/mostimali/p/17813482.html

相关文章

  • AtCoder Beginner Contest(abc) 327
    B-A^A难度:⭐题目大意给出一个数n,问是否存在一个数m,使mm=n;解题思路因为n的数据范围很大,到1e18,经过打表可以发现,当m=16时就已经大于1e18了,因为数很多所以用了__int128,因为double会损失精度;神秘代码#include<bits/stdc++.h>#defineintlonglon......
  • 『AtCoder做题记录』I
    放假之后回机房第一天,后面洛谷永久封了,第一次尝试AT随便打打,先试试不知道那场比赛T1题面:InAtCodercity,therearefiveantennasstandinginastraightline.TheyarecalledAntenna\(A,B,C,D\)and\(E\)fromwesttoeast,andtheircoordinatesare\(a,b,c,......
  • abc327G
    很容易发现条件其实就是限制二分图。那么我们设\(F(n,m)\)表示\(n\)个点,\(m\)条边组成二分图的答案(非简单图)。那么答案可以发现是\(F(n,m)\cdot2^m\),\(2^m\)出自边的端点的两种顺序。现在来计算\(F(n,m)\)。我们这里的\(m\)很大,会达到\(1e9\)的级别,这时候很难用......
  • AtCoder Beginner Contest(abc) 317
    B-MissingNo.难度:⭐题目大意给定n个数,这n个数中最小值到最大值之间缺一个数,输出这个数;解题思路数据不大,暴力即可;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio(false),cin.tie(0),cout.tie(0)#defineendl......
  • 【杂题乱写】AtCoder-ARC115
    AtCoder-ARC115_FMigration*把问题转化成在某个限制\(mid\)下求初始局面和最终局面能到达的最小代价局面,如果相等则说明可达。比较局面的方式是比较权值,如果相等按字典序比较。对每个节点\(u\)求出权值比\(u\)小或权值与\(u\)相等且编号比\(u\)小的节点中,与\(u\)......
  • HHKB Programming Contest 2023(AtCoder Beginner Contest 327) 赛后总结
    HHKBProgrammingContest2023(AtCoderBeginnerContest327)赛后总结又没来得及写题解。。。赛时A-ab查找ab和ba,只要其中一者存在就行。#include<bits/stdc++.h>usingnamespacestd;intn;strings;intmain(){cin>>n>>s;cout<<(s.find("a......
  • Japan Registry Services (JPRS) Programming Contest 2023 (AtCoder Beginner Contes
    JapanRegistryServices(JPRS)ProgrammingContest2023(AtCoderBeginnerContest324)赛后总结可悲的是:我没来得及写题解。TaskASame秒切。直接输入排一遍序再遍历即可。#include<bits/stdc++.h>usingnamespacestd;intn,a[101];intmain(){cin>>n;......
  • [ABC327G] Many Good Tuple Problems 题解
    题意对于一对长度均为\(M\)且元素值在\(\left[1,N\right]\)之间的序列\((S,T)\),定义其为好的当且仅当:存在一个长度为\(N\)的\(01\)序列\(X\),使得其满足如下条件:对于任意\(i\in\left[1,M\right]\),有\(X_{S_i}\neqX_{T_i}\)。给定\(N,M\),求在所有可......
  • ABC327 总结
    A傻逼题,降智吃了一发罚时。B依旧是傻逼题,std::pow炸精度又吃了一发罚时。C傻逼题,切了D发现就是个判断二分图,切了。E一眼丁真,感觉最后一个一定是最大的,然后就是求以最大的结尾的LIS。交上去,喜提WA29。转变思路,考虑dp。设\(f_{i,j}\)表示当前选了\(i\)个(从后往......
  • HHKB Programming Contest 2023(AtCoder Beginner Contest 327)
    HHKBProgrammingContest2023(AtCoderBeginnerContest327)A-abintmain(){IOS;strings;cin>>n>>s;boolf=false;for(inti=1;i<n;++i)if(s[i-1]=='a'&&s[i]=='b&#......