首页 > 其他分享 >Codeforces Round 921 (Div. 2)

Codeforces Round 921 (Div. 2)

时间:2024-01-29 16:45:59浏览次数:27  
标签:std pre int LL cin Codeforces 区间 921 Div

目录

写在前面

比赛地址:https://codeforces.com/contest/1925

在床上躺了两天终于复活了妈的。

A

发现字符串 \(s\) 合法当且仅当 \(s\) 可以被分为至少 \(n\) 段,其中每段都包含 \(k\) 种字符至少 1 次

正确性可以归纳证明,这里懒得写了感性理解下。

于是只需构造:abc...abc...abc......

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
//=============================================================
//=============================================================
//=============================================================
int main() {
  //freopen("1.txt", "r", stdin);
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  int T; std::cin >> T;
  while (T --) {
    int n, k; std::cin >> n >> k;
    for (int i = 1; i <= n; ++ i) {
      for (int j = 0; j < k; ++ j) {
        printf("%c", (char) 'a' + j);
      }
    }
    printf("\n");
  }
  return 0;
}
/*
abc cba abc
*/

B

典中典之枚举 \(\operatorname{gcd}\)。

考虑枚举 \(x\) 的因数 \(d\),检查答案是否可以为 \(d\),即检查是否存在 \(\frac{x}{d}\ge n\)(可以被分为大于 \(n\) 份)即可。

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
//=============================================================
//=============================================================
//=============================================================
int main() {
  //freopen("1.txt", "r", stdin);
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  int T; std::cin >> T;
  while (T --) {
    int x, n, ans = 1; std::cin >> x >> n;
    for (int i = 1; i * i <= x; ++ i) {
      if (x % i != 0) continue;
      if (x / i >= n) ans = std::max(ans, i);
      if (x / (x / i) >= n) ans = std::max(ans, x / i);
    }
    std::cout << ans << "\n";
  }
  return 0;
}

C

A 题,何时又来了?

唏,可以和解吗?

套用 A 的结论:字符串 \(s\) 合法当且仅当 \(s\) 可以被分为至少 \(n\) 段,其中每段都包含 \(k\) 种字符至少 1 次,在顺序枚举字符的同时检查当前一段中是否已经有了 \(k\) 种字符,若满足则分一段,最后检查是否分了不少于 \(n\) 段来判断字符串合法。

然后考虑如何找到在不合法的字符串里的一个未出现过的子序列。考虑在上述过程中某不合法字符串被分为了 \(m(m<n)\) 段出现了 \(k\) 种字符的以及最后一段未出现 \(k\) 种字符的,设这 \(m\) 段中最晚出现的字符为 \(c_i(1\le i\le m)\),最后一段中 \(c_{j}\) 没有出现,则可证明:\(t = c_1c_2\cdots c_m c_j (|t| \le n)\) 没有出现。

其正确性可以考虑反证+归纳:

  • 若 \(m=0\),则 \(c_j\) 未在 \(s\) 中出现过,显然上述结论正确。
  • 否则若 \(t\) 在 \(s\) 中出现过,说明结尾的 \(c_j\) 一定来自于第 \(m\) 段,且该位置一定在第 \(m\) 段的 \(c_m\) 之前,而该位置之前的部分只能被分为 \(m-1\) 段出现了 \(k\) 种字符的以及最后一段未出现 \(c_m\) 的,归纳可知无法表示出 \(t\) 的前缀 \(c_1c_2\cdots c_m\),反证上述结论正确。

要求输出长度为 \(n\) 的,则在 \(t\) 后面随便补什么东西就行。

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
//=============================================================
//=============================================================
//=============================================================
int main() {
  // freopen("1.txt", "r", stdin);
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  int T; std::cin >> T;
  while (T --) {
    int n, k, m; std::cin >> n >> k >> m;
    std::string s, t; std::cin >> s;

    int cnt = 0, cnt1 = 0, cnt2[30] = {0};
    for (int i = 0; i < m; ++ i) {
      ++ cnt2[s[i] - 'a'];
      if (cnt2[s[i] - 'a'] == 1) ++ cnt1;
      if (cnt1 == k) {
        t.push_back(s[i]);
        ++ cnt;
        cnt1 = 0;
        for (int j = 0; j < 26; ++ j) cnt2[j] = 0;
      }
    }

    if (cnt >= n) {
      std::cout << "YES\n";
    } else {
      std::cout << "NO\n";
      for (int i = 0; i < k; ++ i) {
        if (!cnt2[i]) {
          if (t.size() < n) t.push_back((char) (i + 'a'));
          while (t.size() < n) t.push_back('a');
          std::cout << t << "\n";
          break;
        }
      }
    } 
  }
  return 0;
}
/*
aabbcccc 

cab

ab

cccaabb
ccbba
*/

D

期望,懒了。

E

呃呃数据结构。

发现这若干个太空港实际上将 \(1\sim n\) 划分成了若干个区间,每个区间内部的贡献都是一个公差为左侧太空港的价值,项数为与右侧太空港距离的等差数列的形式。

这东西长得太分块了哈哈,考虑将询问拆成中间的完整区间与两端点所在的不完整区间的形式。端点位于的区间可以使用 set 求前驱后继得到,等差数列求和即得不完整区间贡献;中间的完整区间考虑预处理出其贡献并存到其左端点上,再用树状数组维护区间和即可。

修改操作相当于将一个完整区间拆成两个区间,发现被影响的位置仅有原来区间的左端点与当前新加入的位置,树状数组单点修改即可。

修改和查询均为 \(O(\log n)\) 级别,总时间复杂度 \(O((m+q)\log n)\) 级别。

代码中为了方便查询操作求不完整区间(主要是两端点在同一区间内的情况)的贡献,钦定了查询的端点位置上不能有太空港,若有则找到区间内最近的非太空港位置再查询,同样使用了 set 维护。

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
#define pii std::pair<int,int>
#define mp std::make_pair
const int kN = 3e5 + 10;
//=============================================================
int n, m, q, num;
int p[kN], v[kN], id[kN];
std::set <pii> h;
std::set <int> noth;
//=============================================================
namespace BIT {
  #define lowbit(x) ((x)&(-x))
  int lim;
  LL s[kN];
  void Init(int lim_) {
    lim = lim_;
  }
  void Insert(int pos_, LL val_) {
    for (int i = pos_; i <= lim; i += lowbit(i)) {
      s[i] += val_;
    }
  }
  LL Sum(int pos_) {
    LL ret = 0;
    for (int i = pos_; i; i -= lowbit(i)) {
      ret += s[i];
    }
    return ret;
  }
  LL Query(int L_, int R_) {
    if (L_ > R_) return 0;
    return Sum(R_) - Sum(L_ - 1);
  }
  
  #undef lowbit
}
LL Calc(LL val_, LL dis_) {
  return 1ll * (dis_ + 1ll) * dis_ / 2ll * val_;
}
void Init() {
  std::cin >> n >> m >> q;
  BIT::Init(n);
  for (int i = 0; i <= n + 1; ++ i) noth.insert(i);

  for (int i = 1; i <= m; ++ i) {
    std::cin >> p[++ num];
    id[p[i]] = i;
    h.insert(mp(p[i], i)), noth.erase(p[i]);
  }
  for (int i = 1; i <= m; ++ i) std::cin >> v[i];
  for (int i = 1; i <= m; ++ i) {
    std::set <pii>::iterator it = h.lower_bound(mp(p[i], i));
    int pre = (-- it)->second;
    if (p[i] > 1) BIT::Insert(p[pre], Calc(v[pre], p[i] - p[pre] - 1));
  }
}
void Modify(int p_, int v_) {
  std::set <pii>::iterator it = h.lower_bound(mp(p_, num));
  int suf = it->second, pre = (-- it)->second;

  BIT::Insert(p[pre], Calc(v[pre], p_ - p[pre] - 1) - BIT::Query(p[pre], p[pre]));
  BIT::Insert(p_, Calc(v_, p[suf] - p_ - 1));
  
  p[++ num] = p_, v[num] = v_, id[p_] = num;
  h.insert(mp(p_, num)), noth.erase(p_);
}
LL Query(int l_, int r_) {
  if (id[l_]) l_ = *noth.lower_bound(l_);
  if (id[r_]) {
    std::set <int>::iterator it = noth.lower_bound(r_);
    r_ = *(-- it);
  }
  if (l_ > r_) return 0ll;

  int prel, prer, sufl, sufr;
  std::set <pii>::iterator it = h.lower_bound(mp(l_, num));
  sufl = it->second, prel = (-- it)->second;
  it = h.lower_bound(mp(r_, num));
  sufr = it->second, prer = (-- it)->second;
  
  if (prel == prer) {
    return Calc(v[prel], p[sufl] - l_) - Calc(v[prer], p[sufr] - (r_ + 1));
  }
  LL ret = BIT::Query(p[sufl], p[prer] - 1);
  ret += Calc(v[prel], p[sufl] - l_);
  ret += Calc(v[prer], p[sufr] - p[prer] - 1) - Calc(v[prer], p[sufr] - (r_ + 1));
  return ret;
}
//=============================================================
int main() {
  // freopen("1.txt", "r", stdin);
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  Init();
  while (q --) {
    int op, x, y; std::cin >> op >> x >> y;
    if (op == 1) Modify(x, y);
    else std::cout << Query(x, y) << "\n";
  }
  return 0;
}

写在最后

学到了什么:

  • E:贡献为不相交区间形式,且修改等价于将某区间一分为二,考虑整区间与散区间的贡献。

标签:std,pre,int,LL,cin,Codeforces,区间,921,Div
From: https://www.cnblogs.com/luckyblock/p/17994839

相关文章

  • CodeTON Round 7 (Div. 1 + Div. 2, Rated, Prizes!)
    CodeTONRound7(Div.1+Div.2,Rated,Prizes!)比赛链接A.JaggedSwaps思路:考虑到题目要求,给定的排列第一位必须是1才会构造出可行性序列,如果不是就是没有办法Code#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongvoidsolve(){ intn; cin......
  • Codeforces Round 921 (Div. 2)
    A-WeGotEverythingCovered!难度:⭐题目大意给定n和k两个整数,要求用前k个小写字母组成一个字符串;该字符串的子串应包含所有由前k个字母组成的长度为n的字符串全排列;要求输出最短的满足条件的字符串;解题思路这题题目挺唬人,但其实是个水题;所谓最短,其实......
  • CF337E Divisor Tree
    题意简述定义DivisorTree为一棵树:叶子上的数为质数。非叶子上的数为其所有儿子上的数的乘积。给定\(n\)个数\(a_i\),你需要让每个\(a_i\)都在DivisorTree上出现,并最小化DivisorTree的节点数量。\(n\le8,a_i\le10^6\)。分析显然DivisorTree上只能有质数......
  • Codeforces Round 921 (Div. 2)(A~E)
    好久不打用小号水了一场,赛时坑坑拌拌勉强四题,以为美美上分,结果重测时卡掉了我没细想复杂度就交了的B题,这下小丑了 A.WeGotEverythingCovered!直接输出n次连续前k个字母即可#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongsignedmain(){ ios......
  • Codeforces Round 921 (Div. 2)
    CodeforcesRound921(Div.2)A-WeGotEverythingCovered!解题思路:以前\(k\)个字符都出现过至少一次为一轮,构造\(n\)轮即可。代码:#include<bits/stdc++.h>usingnamespacestd;usingll=longlong;usingpii=pair<ll,ll>;#definefifirst#definesesecon......
  • Codeforces Round 920 (Div. 3)
    A-Square难度:⭐题目大意给定正方形的四个顶点,求该正方形的面积;解题思路根据四个点找出长和宽即可,因为数据范围有负数,为了方便我都进行了移位;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio(false);cin.tie(0......
  • Codeforces Round 921 (Div. 2) A-D
    倒叙讲题预警()传送门:https://codeforces.com/contest/1925D.GoodTrip题意:有n个小盆友,其中m对是好盆友,每队好盆友有友谊度fi。老师要举办k次远足,每次挑一对小盆友去,被挑到的小盆友友谊值+1。如果一对儿童不是朋友,那么他们的友谊值为0,在以后的游览中不会改变。求所有被选中参......
  • Codeforces Round 921 (Div. 1) 记录(A-D)
    比赛链接:https://codeforces.com/contest/1924官解链接:https://codeforces.com/blog/entry/125137这场整体来说表现还可以,最终performance\(2431\),delta\(+33\)。A.DidWeGetEverythingCovered?还不错的贪心题。进入状态有点慢,写了几个小错误B.SpaceHarbourC.Frac......
  • Codeforces Round 921 (Div. 2) 赛后总结
    搜索替换int->longlong是一个好习惯赛后5分钟就改对E题了,好可惜。不过1个小时都没能做出来,也说明自己不太熟练吧线段树善于维护满足区间可加性的一类信息,这与本题中的代价和相契合。特殊之处在于其修改方式。每个区间会在线段树上被划分为\(O(log_{2}n)\)个小区间即使是最......
  • Codeforces Round 921 (Div. 2)
    CodeforcesRound921(Div.2)比赛地址A.WeGotEverythingCovered!思路这个就是一个简单的拼接,这里很容易的发现我们最后最优的方法就是将所要拼写的字母按顺序拼接成n份就好了,但是这里需要主义一下简单的优化Code#include<bits/stdc++.h>usingnamespacestd;#define......