Codeforces Round #702 (Div. 3)

题目 A B C D E F G
场上成绩 AC AC AC WA
场后成绩 AC AC AC AC AC AC AC
是否看题解 N N N N Y N Y

说在前面

草,E题挂了,没开long long。

A

如果\((a_i,a_{i + 1})\)不满足,那么\(a_i \leftarrow 2 \cdot a_i\)

# include <bits/stdc++.h>
using namespace std;

const int N = 100;

int t;
int n;
int a[N];

int dfs(int l,int r)
{
    // printf("l = %d,r = %d\n",min(l,r),max(l,r));
    if(double(max(l,r)) / double(min(l,r)) <= 2.0)
    {
        return 0;
    }
    int mid = min(2 * min(l,r),max(l,r));
    int s = dfs(l,mid) + dfs(r,mid) + 1;
    // printf("l = %d, r = %d, s = %d,mid = %d\n",l,r,s,mid);
    return s;
}

int main(void)
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
        }
        int total = 0;
        for(int i = 1; i < n; i++)
        {
            total += dfs(a[i],a[i + 1]);
        }
        printf("%d\n",total);
    }
    return 0;
}

B

求出现在的\(c_0',c_1',c_2'\),分类讨论:

  • 如果都相等,不用改
  • 如果$ > \frac{n}{3}$的有一个,就分给另外两个、
  • 如果$ > \frac{n}{3}$的有两个,就分给另外一个。
# include <bits/stdc++.h>

using namespace std;

const int N = 3e4 + 5;

int n,t;
int a[N];

map<int,map<int,int> > dp;

int c[3];

int delta[3];

int Get(int i,int j)
{
    if(i == j) return 0;
    if(i == 0 && j == 1) return 1;
    if(i == 0 && j == 2) return 2;
    if(i == 1 && j == 2) return 1;
    if(i == 1 && j == 0) return 2;
    if(i == 2 && j == 0) return 1;
    if(i == 2 && j == 1) return 2;
}

int main(void)
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        memset(c,0,sizeof(c));
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            a[i] = a[i] % 3;
            ++c[a[i]];
        }
        int Begin = n / 3;
        vector <int> C,D;
        for(int i = 0; i <= 2; i++) 
        {
            delta[i] = c[i] - Begin;
            if(delta[i] < 0) C.push_back(i);
            else if(delta[i] > 0) D.push_back(i);
        }
        int ans = 0;
        if(D.size() == 0)
        {
            printf("0\n");
            continue;
        }
        else
        {
            if(D.size() == 1)
            {
                for(int i = 0; i < (int)C.size(); i++)
                {
                    int v = C[i];
                    ans += (-delta[v]) * Get(D[0],v);
                }
            }
            else
            {
                //Give C[0]
                ans += (delta[D[0]]) * Get(D[0],C[0]) + (delta[D[1]]) * Get(D[1],C[0]);
            }
        } 
        printf("%d\n",ans);

    }   
    return 0;
}

C

暴力枚举\(a\),然后\(b = \sqrt[3]{x - a^3}\),判断一下有没有整数解,我这里用的二分,\(\mathcal{O}(\sqrt[3]{n}\log{\sqrt[3]{n}})\)

# include <bits/stdc++.h>

using namespace std;
# define int long long
int t;
long long x;

long long qfind(long long x,int i)
{
    long long ans = 0;
    long long l = 1, r = i;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(mid * mid * mid == x) 
        {
            return ans = mid;
        }
        else
        {
            if(mid * mid * mid > x) r = mid - 1; 
            else l = mid + 1;
        }
    }
    return ans;
}

bool check(void)
{
    for(long long i = 1; i * i * i <= x; i++)
    {
        long long s = qfind(x - i * i * i,i);
        if(s) 
        {
            return 1;
        }
    }
    return 0;
}

signed main(void)
{
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&x);
        printf("%s\n",check() ? "YES" : "NO");
    }
    return 0;
}

D

根据题意暴力模拟,最大值位置用ST表。单组询问\(\mathcal{O}(n\log{n} + n)\)

# include <bits/stdc++.h>
using namespace std;

const int N = 105;

int t,n;

vector <int> g[N];

int a[N];

int ST[N][15];

int Log[N];

int id[N];

int root = 0;

void RMQ1(void)
{
    for(int i = 1; i <= n; i++)
    {
        ST[i][0] = a[i];
    }
    for(int j = 1; (1 << j) <= n; j++)
    {
        for(int i = 1; i + (1 << j) - 1 <= n; i++)
        {
            ST[i][j] = max(ST[i][j - 1],ST[i + (1 << (j - 1))][j - 1]);
        }
    }
}

int Get(int l,int r)
{
    int mid = Log[r - l + 1];
    return max(ST[l][mid],ST[r - (1 << mid) + 1][mid]);
}

int build(int l,int r) // return : root
{
    if(l == r)
    {
        return l;
    }
    int maxi = id[Get(l,r)];
    int L = 0,R = 0;
    if(l <= maxi - 1) L = build(l,maxi - 1);
    if(maxi + 1 <= r) R = build(maxi + 1,r);
    if(L) 
    {
        g[maxi].push_back(L);
        g[L].push_back(maxi);
    }
    if(R)
    {
        g[maxi].push_back(R);
        g[R].push_back(maxi);
    }
    return maxi;
}

int dep[N];

void dfs(int x,int fa)
{
    for(int i = 0; i < (int)g[x].size(); i++)
    {
        int v = g[x][i];
        if(v == fa) continue;
        dep[v] = dep[x] + 1;
        dfs(v,x);
    }
    return;
}

int main(void)
{
    scanf("%d",&t);
    Log[2] = 1;
    for(int i = 3; i <= 100; i++) Log[i] = Log[i / 2] + 1;
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            id[a[i]] = i;
        }
        RMQ1();
        for(int i = 1; i <= n; i++)g[i].clear();
        root = build(1,n);
        dep[root] = 0;
        dfs(root,0);
        for(int i = 1; i <= n; i++)
        {
            printf("%d ",dep[i]);
        }
        putchar('\n');
    }
    return 0;
}

E

排个序,如果第\(i\)个选手是有几率赢的,考虑最优状况,每次都遇到当前最小的值,如果累计的值小于当前最小,那么这个就不行,否则行。
那么枚举每个数,并且模拟,\(\mathcal{O}(n^2)\)
这样显然过不去。
然后我们想到:

在排序后,如果第\(i\)个行,那么它后面的都行。
那么我们考虑枚举这个最小的行的值,\(\mathcal{O}(n\log{n})\)

# include <bits/stdc++.h>

using namespace std;

# define int long long 

const int N = 2e5 + 5;

int t,n;

struct node
{
    int soc;
    int x;
}a[N];

bool flag[N];

bool compare(const struct node &x,const struct node &y) {return x.x < y.x;}

bool check(int x)
{
    int tot = a[x].x;
    for(int i = 1; i <= n; i++)
    {
        if(i == x) continue;
        if(a[i].x <= tot) tot += a[i].x;
        else return false;
    }
    return true;
}

int qfind(void)
{
    int l = 1,r = n;
    int ans = n;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(check(mid))
        {
            r = mid - 1;
            ans = mid;
        }
        else l = mid + 1;
    }
    return ans;
}

signed main(void)
{
    scanf("%lld",&t);
    while(t--)
    {
        scanf("%lld",&n);
        memset(flag,0,sizeof(flag));
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld",&a[i].x);
            a[i].soc = i;
            // flag[i] = 0;
        }
        sort(a + 1,a + n + 1,compare);
        // int total = 0;
        int tot = 0;
        int C = qfind();
        for(int i = C; i <= n; i++)
        {
            flag[a[i].soc] = 1;
            ++tot;
        }
        printf("%lld\n",tot);
        for(int i = 1; i <= n; i++)
        {
            if(flag[i])
            {
                printf("%lld ",i);
            }
        }
        putchar('\n');
    }
    return 0;
}

F

考虑将每个数的出现的次数求出来,但是\(a_i \le 10^9\),就得离散化一下,设其为\(c_i\)
\(c\)排序,枚举\(C\),对于每个\(c_i\),如果\(c_i < C\),就得消到\(0\),如果\(c_i > C\),就得消到\(C\)
答案即为

\[\sum_{i \in \{x \mid c_x < C\}} c_x + \sum_{i \in \{x \mid c_x > C\}} {c_x - C} \]

整个前缀和。\(\mathcal{O}(n\log{n})\)

# include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;

int t,n;
int a[N],b[N],c[N];
long long q[N];

int qfind(int C)
{
    int l = 1, r = n;
    int ans = n;
    while(l <= r)
    {
        int mid = (l + r) >> 1;
        if(c[mid] < C)
        {
            ans = mid;
            l = mid + 1;
        }
        else r = mid - 1;
    }
    return ans;
}

int main(void)
{
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(int i = 1; i <= n; i++) c[i] = 0;
        for(int i = 1; i <= n; i++)
        {
            scanf("%d",&a[i]);
            b[i] = a[i];
        }
        sort(b + 1, b + n + 1);
        int Len = unique(b + 1, b + n + 1) - b - 1;
        for(int i = 1; i <= n; i++)
        {
            a[i] = lower_bound(b + 1, b + Len + 1, a[i]) - b;
            ++c[a[i]];
        }
        // sort(a + 1, a + n + 1);
        sort(c + 1, c + n + 1);
        bool flag = 1;
        for(int i = 1; i < n; i++)
        {
            if(c[i] != c[i + 1])
            {
                flag = 0;
                break;
            }
        }
        if(flag)
        {
            printf("0\n");
            continue;
        }
        q[0] = 0;
        for(int i = 1; i <= n; i++)
        {
            q[i] = q[i - 1] + c[i];
        }
        int ans = n;
        for(int C = 0; C <= n; C++)
        {
            int w = qfind(C);
            int ANS = 0;
            ANS = q[w];
            ANS = ANS + q[n] - q[w];
            ANS = ANS - (n - w) * C;
            ans = min(ans,ANS);
        }
        printf("%d\n",ans);
    }
    return 0;
}

G

\(q_i = \sum_{j = 1} ^ i a_j,Max_i = \max_{j = 1} ^ i \{q_j\}\)

显而易见: 如果\(Max_n < x\)\(q_x \le 0\),输出\(-1\)

显而易见\(r = \left \lceil \dfrac{x - Max_n}{q_n} \right \rceil\),其中\(r\)为对于询问\(x\)整圈数

证明: 最小化\(r \cdot q_n + Max_n \ge x (r \in \mathbb{N_+})\),显然取\(r = \left \lceil \dfrac{x - Max_n}{q_n} \right \rceil\)

如果还有残圈就在\(Max\)里二分就行,\(Max\)显然具有单调性,即\(Max_i \ge Max_{i - 1}(1 < i \le n)\)

# include <bits/stdc++.h>
using namespace std;

const int N = 2e5 + 5;

int t,n,m;
long long a[N];
long long x[N];
long long q[N],Max[N];
int main(void)
{
    // freopen("G.out","w",stdout);
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d%d",&n,&m);
        for(int i = 1; i <= n; i++)
        {
            scanf("%lld",&a[i]);
        }
        for(int i = 0; i <= n; i++) Max[i] = -1e12;
        for(int i = 1; i <= n; i++) 
        {
            q[i] = q[i - 1] + a[i];
            Max[i] = max(Max[i - 1],q[i]);
        }
        for(int i = 1; i <= m; i++)
        {
            scanf("%lld",&x[i]);
            if(Max[n] < x[i] && q[n] <= 0)
            {
                printf("-1 ");
                continue;
            }
            long long r = 0;
            if(Max[n] < x[i])
            {
                r = ceil(double(x[i] - Max[n]) / double(q[n]));
                x[i] -= r * q[n]; 
            }
            int j = lower_bound(Max + 1, Max + n + 1, x[i]) - Max;
            printf("%lld ",r * n + j - 1);
           
        }
        putchar('\n');
    }
    return 0;
}
posted @ 2021-02-17 10:05  luyiming123  阅读(98)  评论(0编辑  收藏  举报