Codeforces Round #595 (Div. 3)

比赛链接:传送门



Codeforces1249A. Yet Another Dividing into Teams(水题)

代码:

#include <bits/stdc++.h>
#define N 105

using namespace std;

int a[N];
int main()
{
    int q;
    cin >> q;
    while (q--) {
        int n; cin >> n;
        for (int i = 1; i <= n; i++) {
            cin >> a[i];
        }
        sort(a+1, a+1+n);
        int ans = 1;
        for (int i = 2; i <= n; i++) {
            if (a[i] == a[i-1] + 1) {
                ans++;
                break;
            }
        }
        cout << ans << endl;
    }
    return 0;
}



Codeforces1249B2. Books Exchange (hard version)

一本书在一个周期内经过的路径中的每个人,拿到自己原来的书所需要的时间都等于这个周期的长度。

代码:O(n)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl ‘\n‘
#define lowbit(x) (x&-x)

using namespace std;
typedef long long ll;
typedef double db;

/** fast read **/
template <typename T>
inline void read(T &x) {
    x = 0; T fg = 1; char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == ‘-‘) fg = -1;
        ch = getchar();
    }
    while (isdigit(ch)) x = x*10+ch-‘0‘, ch = getchar();
    x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
    int len = 0; char c[21]; if (x < 0) putchar(‘-‘), x = -x;
    do{++len; c[len] = x%10 + ‘0‘;} while (x /= 10);
    for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }

ll gcd(ll a, ll b) {
    return b == 0 ? a : gcd(b, a%b);
}

int p[N], ans[N];
int solve(int x) {
    int len = 0;
    int tmp = x;
    do {
        tmp = p[tmp];
        len++;
    } while (tmp != x);
    do {
        ans[tmp] = len;
        tmp = p[tmp];
    } while (tmp != x);
    return len;
}
int main()
{
    int q;
    cin >> q;
    while (q--) {
        int n; read(n);
        for (int i = 1; i <= n; i++) {
            ans[i] = 0;
        }
        for (int i = 1; i <= n; i++)
            read(p[i]);
        for (int i = 1; i <= n; i++) {
            if (!ans[i]) {
                solve(i);
            }
        }
        for (int i = 1; i <= n; i++) {
            printf("%d%c", ans[i], " \n"[i==n]);
        }
    }
    return 0;
}



Codeforces1249C2. Good Numbers (hard version)(进制转换 贪心)

把n转化成三进制放在数组中,如果有2的话说明要找比n大的最小的满足条件的。

只要把权值最大的2加一变成3,然后进位。并把比这个2小的所有三进制数值置零就行了。

比如129用三进制表示是1121。操作过程中的值就是:1121->1200->2000->10000。结果就是35 = 243。

代码:O(logn)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl ‘\n‘
#define lowbit(x) (x&-x)

using namespace std;
typedef long long ll;
typedef double db;

/** fast read **/
template <typename T>
inline void read(T &x) {
    x = 0; T fg = 1; char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == ‘-‘) fg = -1;
        ch = getchar();
    }
    while (isdigit(ch)) x = x*10+ch-‘0‘, ch = getchar();
    x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
    int len = 0; char c[21]; if (x < 0) putchar(‘-‘), x = -x;
    do{++len; c[len] = x%10 + ‘0‘;} while (x /= 10);
    for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }

ll b[N], a[N];
int main()
{
    b[0] = 1;
    for (int i = 1; i <= 38; i++) {
        b[i] = b[i-1] * 3;
    }
    int q; read(q);
    while (q--) {
        ll n; read(n);
        for (int i = 38; i >= 0; i--) {
            a[i] = n/b[i];
            n %= b[i];
        }
        int st = 0;
        for (int i = 38; i >= 0; i--) {
            if (a[i] == 2) {
                st = i;
                break;
            }
        }
        for (int i = 0; i < st; i++) {
            a[i] = 0;
        }
        for (int i = st; i <= 38; i++) {
            if (a[i] >= 2) {
                a[i] = 0;
                a[i+1]++;
            }
        }
        ll ans = 0;
        for (int i = 0; i <= 38; i++) {
            if (a[i])
                ans += b[i];
        }
        cout << ans << endl;
    }
    return 0;
}



Codeforces1249D2. Too Many Segments (hard version)(扫描线+单调队列+multiset维护)

这题好像比E难的样子。

思路:

考虑从左到右枚举每一个小区间,看这个小区间被多少个线段覆盖。如果被超过k个线段覆盖,则把这些线段中右端点最大的一个remove掉。

实现:

先把所有线段按l、r从小到大排序,然后从左到右遍历。

对于每一条线段(l0,r0),考虑维护之前有多少个线段的r比l0大。具体的就是保存之前的所有的r,如果r < l0,则把这些r删去。(这里可以用单调队列或者set维护,但是考虑后面的操作,这里选择了set)

如果比l0大的r的数量超过了k,那么就贪心地删去里面最大的那个r(这里就体现了set的方便之处,可以直接erase(--set.end()))。考虑到会有重复元素,所以set要换成multiset。

代码:O(nlogk)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl ‘\n‘
#define lowbit(x) (x&-x)

using namespace std;
typedef long long ll;
typedef double db;

/** fast read **/
template <typename T>
inline void read(T &x) {
    x = 0; T fg = 1; char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == ‘-‘) fg = -1;
        ch = getchar();
    }
    while (isdigit(ch)) x = x*10+ch-‘0‘, ch = getchar();
    x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
    int len = 0; char c[21]; if (x < 0) putchar(‘-‘), x = -x;
    do{++len; c[len] = x%10 + ‘0‘;} while (x /= 10);
    for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }

struct Node{
    int l, r, id;
    bool operator < (const Node& x) const {
        if (l == x.l)
            return r < x.r;
        return l < x.l;
    }
}nodes[N];

struct SNode{
    int val, id;
    bool operator < (const SNode& x) const {
        return val < x.val;
    }
};

multiset <SNode> S;
vector <int> ans;
int main()
{
    int n, k; read(n, k);
    for (int i = 1; i <= n; i++) {
        read(nodes[i].l, nodes[i].r);
        nodes[i].id = i;
    }
    sort(nodes+1, nodes+1+n);
    for (int i = 1; i <= n; i++) {
        while (!S.empty() && (*S.begin()).val < nodes[i].l)
            S.erase(S.begin());
        S.insert(SNode{nodes[i].r, nodes[i].id});
        if (sz(S) > k) {
            ans.push_back((*--S.end()).id);
            S.erase(--S.end());
        }
    }
    sort(ans.begin(), ans.end());
    cout << ans.size() << endl;
    for (int i = 0; i < sz(ans); i++) {
        printf("%d%c", ans[i], " \n"[i == sz(ans)-1]);
    }
    return 0;
}



Codeforces1249E. By Elevator or Stairs?(dp)

思路:

上楼肯定是要一层一层上的,所以每层楼只要考虑下面那层楼爬到这一层楼的情况。

设当前楼层为i,$f_{i,0/1}$表示到达第i层楼时,最后一层是走楼梯(0)或者电梯(1)所需要的最短时间。

显然有$f_{1,0} = 0$,特别地,令$f_{1,1}=c$。

1、如果我上第i层楼想走楼梯,那么:$f_{i,0} = min(f_{i-1,0}+a_{i-1}, f_{i-1, 1}+a_{i-1})$

2、如果我上第i-1层楼走的楼梯,并且第i层楼想走电梯的话,要花c的时间等电梯:$f_{i,1} = min(f_{i,1}, f_{i-1,0}+c+b_{i-1})$

3、如果我上第i-1层楼走的电梯,并且第i层楼想走电梯的话,不用再花时间等电梯了:$f_{i,1} = min(f_{i,1}, f_{i-1,1}+b_{i-1})$

显然到达第i层楼的最短时间是$min(f_{i,0}, f_{i,1})$

代码:O(n)

#include <bits/stdc++.h>
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define N 200005
#define M 100005
#define INF 0x3f3f3f3f
#define mk(x) (1<<x) // be conscious if mask x exceeds int
#define sz(x) ((int)x.size())
#define upperdiv(a,b) (a/b + (a%b>0))
#define mp(a,b) make_pair(a, b)
#define endl ‘\n‘
#define lowbit(x) (x&-x)

using namespace std;
typedef long long ll;
typedef double db;

/** fast read **/
template <typename T>
inline void read(T &x) {
    x = 0; T fg = 1; char ch = getchar();
    while (!isdigit(ch)) {
        if (ch == ‘-‘) fg = -1;
        ch = getchar();
    }
    while (isdigit(ch)) x = x*10+ch-‘0‘, ch = getchar();
    x = fg * x;
}
template <typename T, typename... Args>
inline void read(T &x, Args &... args) { read(x), read(args...); }
template <typename T>
inline void write(T x) {
    int len = 0; char c[21]; if (x < 0) putchar(‘-‘), x = -x;
    do{++len; c[len] = x%10 + ‘0‘;} while (x /= 10);
    for (int i = len; i >= 1; i--) putchar(c[i]);
}
template <typename T, typename... Args>
inline void write(T x, Args ... args) { write(x), write(args...); }

int a[N], b[N];
int f[N][2];// 0 stair 1 elevator
int main()
{
    int n, c; read(n, c);
    for (int i = 1; i < n; i++)
        read(a[i]);
    for (int i = 1; i < n; i++)
        read(b[i]);
    memset(f, 0x3f, sizeof f);
    f[1][0] = 0;
    f[1][1] = c;
    for (int i = 2; i <= n; i++) {
        f[i][0] = min(f[i][0], f[i-1][0] + a[i-1]);
        f[i][0] = min(f[i][0], f[i-1][1] + a[i-1]);
        f[i][1] = min(f[i][1], f[i-1][0] + c + b[i-1]);
        f[i][1] = min(f[i][1], f[i-1][1] + b[i-1]);
    }
    for (int i = 1; i <= n; i++) {
        printf("%d%c", min(f[i][0], f[i][1]), " \n"[i==n]);
    }
    return 0;
}

原文地址:https://www.cnblogs.com/Lubixiaosi-Zhaocao/p/11725120.html

时间: 2024-10-08 06:43:41

Codeforces Round #595 (Div. 3)的相关文章

Codeforces Round #595 (Div. 3) E. By Elevator or Stairs?

题目地址:http://codeforces.com/contest/1249/problem/E 题意:有n层楼,上楼有楼梯和电梯两种方法,从 i 到 i+1 层有不同花费,用电梯有等电梯门开的时间,但上一次用的电梯就不用等这个时间.问去每层楼的最小花费. 思路:很基础的dp题,dp [ i ] [ 0 ] 表示一楼到 i楼的总时间,其中从 i - 1 楼到 i 楼用的是楼梯,dp [ i ] [ 1 ] 表示从一楼到 i 楼的总时间,其中 i - 1 到 i 楼用的电梯. AC代码: 1 #

Codeforces Round #595 (Div. 3)B2 简单的dfs

原题 https://codeforces.com/contest/1249/problem/B2 这道题一开始给的数组相当于地图的路标,我们只需对每个没走过的点进行dfs即可 #include <bits/stdc++.h> using namespace std;const int maxn=2e5+20;int a[maxn],b[maxn],c[maxn];int dfs(int pos,int step){//传递坐标与步数 if(b[pos]==1){//再次遇到b[pos],返回

Codeforces Round #595 (Div. 3) 题解

前言 无 A 因为没有重复的数,我们只要将数据排序,比较两两之间有没有\(a_j - a_i == 1 (j > i)\) 的,有则输出 \(2\) , 无则输出 \(1\) 普及T1难度 Code #include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define N 107 using namespace st

题解Codeforces Round #595 (Div. 3)(CF1249)

开题1小时(雾)严重影响我的提交以及做题心情..我刚开题就发现有人阿克了.. 实际上这场div3真心简单良心很休闲. A:送分题,先排序,每次枚举一下这个数可以加到哪个集合里,加进去就行. 1 #include<stdio.h> 2 #include<algorithm> 3 #define it register int 4 #define il inline 5 using namespace std; 6 const int N=1000005; 7 int a[N],o[N

E. By Elevator or Stairs?.Codeforces Round #595 (Div. 3)

前言 有一说一,这是我做过最简单的一道E题 题意 告诉你有个大楼,然后让你求出从一楼到每一楼的最短时间.其中,上楼有两种方式1.走楼梯2.坐电梯.楼梯可以直接走,电梯需要一个等待时间.数据给出层与层之间不算等待时间的两种方式上楼所需的时间. 做法 很容易想到dp,而且是最基础的dp(估计div3也就敢这么出个算法题) 状态dp[i][0]表示走楼梯上到i层所需的最短时间.dp[i][1]表示坐电梯时上到i层所需的最短时间. 转移方程 dp[i][0]=min(dp[i-1][0],dp[i-1]

Codeforces Round #428 (Div. 2)

Codeforces Round #428 (Div. 2) A    看懂题目意思就知道做了 #include<bits/stdc++.h> using namespace std; #pragma comment(linker, "/STACK:102400000,102400000") #define rep(i,a,b) for (int i=a; i<=b; ++i) #define per(i,b,a) for (int i=b; i>=a; --i

Codeforces Round #424 (Div. 2) D. Office Keys(dp)

题目链接:Codeforces Round #424 (Div. 2) D. Office Keys 题意: 在一条轴上有n个人,和m个钥匙,门在s位置. 现在每个人走单位距离需要单位时间. 每个钥匙只能被一个人拿. 求全部的人拿到钥匙并且走到门的最短时间. 题解: 显然没有交叉的情况,因为如果交叉的话可能不是最优解. 然后考虑dp[i][j]表示第i个人拿了第j把钥匙,然后 dp[i][j]=max(val(i,j),min(dp[i-1][i-1~j]))   val(i,j)表示第i个人拿

Codeforces Round #424 (Div. 2) C. Jury Marks(乱搞)

题目链接:Codeforces Round #424 (Div. 2) C. Jury Marks 题意: 给你一个有n个数序列,现在让你确定一个x,使得x通过挨着加这个序列的每一个数能出现所有给出的k个数. 问合法的x有多少个.题目保证这k个数完全不同. 题解: 显然,要将这n个数求一下前缀和,并且排一下序,这样,能出现的数就可以表示为x+a,x+b,x+c了. 这里 x+a,x+b,x+c是递增的.这里我把这个序列叫做A序列 然后对于给出的k个数,我们也排一下序,这里我把它叫做B序列,如果我

[Codeforces] Round #352 (Div. 2)

人生不止眼前的狗血,还有远方的狗带 A题B题一如既往的丝帛题 A题题意:询问按照12345678910111213...的顺序排列下去第n(n<=10^3)个数是多少 题解:打表,输出 1 #include<bits/stdc++.h> 2 using namespace std; 3 int dig[10],A[1005]; 4 int main(){ 5 int aa=0; 6 for(int i=1;;i++){ 7 int x=i,dd=0; 8 while(x)dig[++dd