首页 > 其他分享 >The 2022 ICPC Asia Nanjing Regional Contest

The 2022 ICPC Asia Nanjing Regional Contest

时间:2024-09-26 20:46:59浏览次数:1  
标签:Contest int Regional mid long 枚举 Nanjing ans 操作

目录

写在前面

补题地址:https://codeforces.com/gym/104128

以下按个人向难度排序。

SUA 什么牛逼提妈的又被斩杀了,wenqizhi 大爹一个人爆切三道我和 dztlb 大神两个人分别在 AM 上调不出来坐牢真是纯纯的战犯

I 签到

显然当且仅当所有字符均相等才为完美回文。

字符集只有 26,直接做就行了。

#include <bits/stdc++.h>
using namespace std;
#define int long long
const int N=1e6+5;
int T;
char s[N];
int a[300];
signed main(){
	cin>>T;
	while(T--){
		scanf("%s",s+1);
		int n=strlen(s+1);
		for(int i=0;i<=100;++i) a[i]=0;
		for(int i=1;i<=n;++i){
			a[s[i]-'a']++;
		}
		int ans=ans=n;
		for(int i=0;i<26;++i){
			ans=min(ans,n-a[i]);
		}
		cout<<ans<<'\n';
	}
	return 0;
}

G 贪心,模拟

显然应当在保证数量大于 0 情况下,尽可能进行操作 -1。

发现这个操作对答案的分数有加有减的很麻烦啊,一个套路是考虑统一操作的形式。考虑先将所有操作均看做一次操作 1(即令分母分子同时加 1),发现操作 -1 可看成再额外对分子减 1,对分母减 2。考虑最终进行了 \(c\) 次操作 -1,则进行 \(n\) 次操作后,最终的答案可以表示为:

\[\frac{n + 1 - c}{n + 1 - 2c} \]

保证上式分母时刻大于 0 即对应一种合法的操作方案。于是一个显然的想法是考虑直接贪心,尽量进行操作 -1,若发现此时进行操作 -1 后会导致上式不合法,则尝试将之前一次操作 -1 反悔即可。

赛时 wenqizhi 的思路是直接模拟上述转化,先将所有操作 0 均看做操作 1,然后考虑将当前的分母的值看做一张折线图,然后再倒序枚举折线图上的点,若当前点对应操作为 0,且在此之后的折线图上最小值至少为 2,则可以将当前的操作贪心地更改为操作 -1。

时间复杂度均为 \(O(n)\) 级别。

code by wenqizhi:

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

#define ll long long
#define ull unsigned long long

int read()
{
    int x = 0; bool f = false; char c = getchar();
    while(c < '0' || c > '9') f |= (c == '-'), c = getchar();
    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15), c = getchar();
    return f ? -x : x;
}

const int N = 1e6 + 5;
int n, a[N], pre[N], sufmn[N];

void solve()
{
    n = read();
    int b = 0;
    for(int i = 1; i <= n; ++i)
    {
        a[i] = read();
        pre[i] = pre[i - 1] + ((a[i] == 0) ? 1 : a[i]), b += (a[i] == -1);
    }
    sufmn[n] = pre[n];
    if(pre[n] < 0){ printf("-1\n"); return ; }
    for(int i = n - 1; i >= 1; --i)
    {
        sufmn[i] = min(pre[i], sufmn[i + 1]);
        if(pre[i] < 0)
        {
            printf("-1\n");
            return ;
        }
    }
    int cnt = 0;
    sufmn[n + 1] = 0x7fffffff;
    for(int i = n; i >= 1; --i)
    {
        sufmn[i] = min(sufmn[i], sufmn[i + 1]);
        if(a[i] == 0)
        {
            if(sufmn[i] >= 2) ++cnt, sufmn[i] -= 2;
        }
    }
    
    int X = n - b - cnt + 1, Y = n - 2 * b - 2 * cnt + 1, mx = max(X, Y);
    for(int i = 2; i <= mx; ++i)
        while(X % i == 0 && Y % i == 0) X /= i, Y /= i;
    printf("%d %d\n", X, Y);
}

int main()
{
    int T = read();
    while(T--) solve();
    return 0;
}

反悔贪心:

//
/*
By:Luckyblock
*/
#include <bits/stdc++.h>
#define LL long long
const int kN = 1e6 + 10;
//=============================================================
int n;
//=============================================================
void getans(int ans_) {
  int x = n + 1 - ans_, y = n + 1 - 2 * ans_;
  int d = std::__gcd(x, y);
  std::cout << x / d << " " << y / d << "\n";
}
//=============================================================
int main() {
  // freopen("1.txt", "r", stdin);
  std::ios::sync_with_stdio(0), std::cin.tie(0);
  int T; std::cin >> T;
  while (T --) {
    std::cin >> n;
    int cnt = 0, ans = 0, flag = 0; 
    for (int i = 1; i <= n; ++ i) {
      int a; std::cin >> a;
      if (a == 1) {
        continue;
      } else if (a == -1) {
        if (2 * (ans + 1) < i + 1) ++ ans;
        else if (cnt) -- cnt;
        else flag = 1;
      } else {
        if (2 * (ans + 1) < i + 1) ++ ans, ++ cnt;
      }
    }
    if (flag) std::cout << -1 << "\n";
    else getans(ans);
  }
  return 0;
}

D 二分答案,枚举

显然答案有单调性,考虑二分答案。问题变为能否使序列中不小于 \(\operatorname{mid}\) 的数的数量不小于 \(k\)。

然后考虑被枚举操作的区间,仅需考虑区间中的 0 中有多少可以变成 1 即可。对于操作区间为 \([1, m]\) 时可以大力处理,然后发现当操作区间右移至 \([i, i + m - 1]\) 时,新加入的数 \(a_{i+m-1}\) 会变为 \(a_{i+m-1} + kd\),原区间内的数均会减 \(d\)。

发现每一个数在操作区间内时,随区间右移其值是单调递减的,即每个数均会在操作区间左端点取 \(i\) 时变为不小于 \(k\),又会在操作区间左端点取 \(i'(i'>i)\) 时变为小于 \(k\),于是考虑将每个数的贡献 \(\plusmn 1\) 分别挂在这两个位置上,则每种操作区间的影响即可通过前缀和求得。

赛时 wenqizhi 大神原理大致如上但是用线段树实现的,一发过了但是看不懂呃呃呃呃:

code by wenqizhi:

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

#define ll long long
#define ull unsigned long long

int read()
{
    int x = 0; bool f = false; char c = getchar();
    while(c < '0' || c > '9') f |= (c == '-'), c = getchar();
    while(c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c & 15), c = getchar();
    return f ? -x : x;
}

const int N = 2e5 + 5;
int n, m, K;
ll c, d, a[N], A[N], b[N];

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)

struct Segment
{
    int sum[N << 2];
    
    void update(int k, int l, int r, int pos, int val)
    {
        sum[k] += val;
        if(l == r) return ;
        int mid = (l + r) >> 1;
        if(pos <= mid) update(ls(k), l, mid, pos, val);
        else update(rs(k), mid + 1, r, pos, val);
    }

    int query(int k, int l, int r, int L, int R)
    {
        if(L <= l && r <= R) return sum[k];
        int mid = (l + r) >> 1;
        if(R <= mid) return query(ls(k), l, mid, L, R);
        if(L > mid) return query(rs(k), mid + 1, r, L, R);
        return query(ls(k), l, mid, L, R) + query(rs(k), mid + 1, r, L, R);
    }
}T1, T2;

ll lazy;
int nn, mm;

bool check(ll mid)
{
    int pos1 = upper_bound(A + 1, A + mm + 1, mid) - A - 1;
    int pos2 = upper_bound(b + 1, b + nn + 1, mid - lazy) - b - 1;
    int sum1 = T1.query(1, 1, mm, 1, pos1), sum2 = T2.query(1, 1, nn, 1, pos2);
    if(sum1 + sum2 >= n - K + 1) return true;
    else return false;
}

int main()
{
    n = read(), K = read(), m = read(), c = read(), d = read();
    for(int i = 1; i <= n; ++i) a[i] = read(), b[i] = a[i] + c + d * (i - 1), A[i] = a[i];
    b[n + 1] = -0x7fffffffffffffff, b[n + 2] = 0x7fffffffffffffff;
    sort(b + 1, b + n + 3);
    nn = unique(b + 1, b + n + 3) - (b + 1);
    A[n + 1] = -0x7fffffffffffffff, A[n + 2] = 0x7fffffffffffffff;
    sort(A + 1, A + n + 3);
    mm = unique(A + 1, A + n + 3) - (A + 1);
    for(int i = 1; i <= m; ++i)
    {
        int id = lower_bound(b + 1, b + nn + 1, a[i] + c + d * (i - 1)) - b;
        T2.update(1, 1, nn, id, 1);
    }
    for(int i = m + 1; i <= n; ++i)
    {
        int id = lower_bound(A + 1, A + mm + 1, a[i]) - A;
        T1.update(1, 1, mm, id, 1);
    }

    ll ans = -0x7fffffffffffffff;

    for(int i = m; i <= n; ++i)
    {
        ll l = -0x7ffffffffffff, r = 0x7ffffffffffff;
        while(l < r)
        {
            ll mid = (l + r) >> 1;
            if(check(mid)) r = mid;
            else l = mid + 1;
        }
        // printf("i = %d, l = %lld\n", i, l);
        ans = max(ans, l);
        if(i < n)
        {
            lazy -= d;
            int lastid = i - m + 1;
            int id = lower_bound(b + 1, b + nn + 1, a[lastid] + c + d * (lastid - 1)) - b;
            T2.update(1, 1, nn, id, -1);
            id = lower_bound(A + 1, A + mm + 1, a[lastid]) - A;
            T1.update(1, 1, mm, id, 1);
            lastid = i + 1;
            id = lower_bound(b + 1, b + nn + 1, a[lastid] + c + d * (lastid - 1)) - b;
            T2.update(1, 1, nn, id, 1);
            id = lower_bound(A + 1, A + mm + 1, a[lastid]) - A;
            T1.update(1, 1, mm, id, -1);
        }
    }
    printf("%lld\n", ans);
    return 0;
}

A 枚举,结论,二维前缀和

和 wenqizhi 大神讨论了下就直接会写了然而直到结束吃了 11 发都没过赛后一看是超级脑瘫错误呃呃

B DP,枚举

我和 dztlb 大神双人红温的时候,wenqizhi 大爹跑去开教练见面会了,到他回来我们也没调出来然后他一个人随便写写就又一发把这题过了唉唉真大神吧

M 计算几何,枚举,大力讨论

沟槽的题 corner case 这么多赛时从 WA30 搞到 WA50 再搞到 WA83 然后再也过不去了

写在最后

唉唉 wenqizhi 大爹太强了感觉我是纯飞物。

学到了什么:

  • A:使用非常人类智慧的表达式,尝试简化特判——并非好事!

标签:Contest,int,Regional,mid,long,枚举,Nanjing,ans,操作
From: https://www.cnblogs.com/luckyblock/p/18434301

相关文章

  • Buildings(AtCoder Beginner Contest 372)
    #include<bits/stdc++.h>#defineendl'\n'usingll=longlong;typedefunsignedlonglongull;usingnamespacestd;voidGordenGhost();signedmain(){#ifdefGordenfreopen("E:/ProgramFiles/CLion2023.2.2/my/exe/in.txt&quo......
  • The 2024 ICPC Asia East Continent Online Contest (II)
    C.PrefixofSuffixes比赛的时候调E,调的心态爆炸,最后一点时间写C,又没冲出来题目大意给三个数组\(\{S_n\},\{a_n\},\{b_n\}\),对于每个\(i\)求\(\sum_{j=1}^i\sum_{k=j}^{j+z_j-1}A_kB_j\),其中\(z_i\)表示\(S_{[1,i]}\)和\(S_{[j,i]}\)的最长公共前缀的长度,\(S\)数组强制在线\[......
  • The 2024 ICPC Asia EC Regionals Online Contest (II)
    A-GamblingonChoosingRegionals题意\(k\)场比赛,每场比赛每个大学至多\(c_i\)个队;总\(n\)个队伍,每队有分数与所属大学两个属性,每只队伍至多参加\(2\)场比赛。求各个队在最坏情况下的最优排名。思路最坏情况就是你打哪场,强队都去哪场,就选\(c_i\)小的场次,能让排名更靠......
  • AtCoder Beginner Contest 372(4/7)
    比赛链接:https://atcoder.jp/contests/abc372开头:过去一个多月了,虽然暑假就上了蓝,但感觉自已一直还没达到蓝的水准,网络赛也打了两场,打的一般,开学之后一直比较忙,现在稳定了下来,接下来打算尽量每周3-4篇atcoder的题解吧,这是这周第一篇,虽然有点水(A.delete.思路:签......
  • The 2024 ICPC Asia East Continent Online Contest (II)
    Preface被徐神带飞咯,全程睡觉看队友卡卡过题,最变态的是K我上去乱写了个假做法就下机睡觉了,后面徐神反手就改了个正解出来这场主要是周五晚上无来由地发烧了,第二天比赛的时候头痛的一批,几乎没法集中精力想代码和写题但没想到这场最后打的还挺好,开局1h不到就把6个签过了,然......
  • The 2024 ICPC Asia East Continent Online Contest (I)
    Preface打的一坨,直接被Div.2学弟吊起来打这场主要是中期的Easy~mid写的太慢,导致中后期题没时间写同时封榜后的决策也有点问题,没有全队All-in一个题而是让徐神去写当时1/27的K,虽然可能徐神来想H我们也出不来但感觉还是跟榜适合我们队的level赛后发现H反着填右括......
  • AtCoder Regular Contest 184 D Erase Balls 2D
    转化计数对象。直接数最终剩下的球的集合似乎并不好做。考虑数选择的球的集合(显然选择的顺序不重要,只有选择了哪些球重要)。先把所有球按\(x\)坐标从小到大排序。设我们选择的球的下标为\(i_1<i_2<\cdots<i_k\)。那么能选择这些球当且仅当\(y_{i_1}>y_{i_2}>\cdots......
  • AtCoder Beginner Contest 372 补题记录
    A-delete题意:输出删除字符串中.后的字符串思路:只输出字符串中不是.的字符voidsolve(){strings=sread();for(autoit:s)if(it!='.')cout<<it;cout<<endl;}B-3^A题意:给出M,求将M拆分成N个3的\(A_i\)次方相加思路:贪心,从大到小用......
  • AtCoder Beginner Contest 372(A - F)
    A:直接输出。B:把\(M\)三进制拆分,最多10位,每位最多为2,\(N\le20\)足够了。C:暴力修改,每次只产生\(O(1)\)影响。D:预处理st表,二分每个\(j\)会断哪些\(i\)产生贡献,差分一下。E:启发式合并平衡树,\(k\)更大也能做。F:只保留有特殊边经过的点,把\(i,j\)之间的\(j-i......
  • The 2024 ICPC Asia EC Regionals Online Contest (II) - Problem H. Points Selectio
    注意到如果$\text{query}(a,b,c)$为真,那么$\text{query}(\geqa,\geqb,c)$一定为真。从小到大枚举询问中$a$的值,按横坐标从小到大依次加入每个点,维护$f_c$表示最小的$b$满足$\text{query}(a,b,c)$为真。假设当前正在加入点$(x,y,w)$,有$f_{(c+w)\bmodn}=\min(f_{......