首页 > 其他分享 >AtCoder Grand Contest 022 E Median Replace

AtCoder Grand Contest 022 E Median Replace

时间:2024-03-13 17:22:18浏览次数:17  
标签:AtCoder typedef stackrel Contest int 010 000 Grand Longrightarrow

洛谷传送门

AtCoder 传送门

考虑对于一个确定的串怎么判断合法性。

容易发现删到某个时刻若 \(1\) 的个数大于 \(0\) 的个数了,因为我们肯定不会蠢到在不是全 \(1\) 的时候删 \(111\),所以 \(c_1 - c_0\) 在不是全 \(1\) 的时候至少是不会变小的。

所以我们的目标就是让 \(c_1 - c_0\) 尽可能大。

发现删 \(000\) 这个操作看起来很优,它能使 \(c_1 - c_0\) 增加 \(2\)。所以我们只要贪心地删 \(000\) 就可以了……吗?

考虑这个串:\(0010011\),删不了 \(000\),并且 \(c_1 - c_0 < 0\)。但是实际上这个串可以先删中间的 \(010\) 变成 \(00011\),再删 \(000\)。发现问题出在没有删 \(010\)。发现删 \(010\) 之后 \(c_1 - c_0\) 不变,并且它左侧和右侧的 \(0\) 可以拼在一起形成一个新的 \(000\)。感性理解一下这个策略是不劣的。

也就是说有 \(000\) 或者 \(010\) 就删。最后判 \(c_1 - c_0\) 是否 \(> 0\) 即可。

考虑计数。可以考虑设计一个自动机,并且记录当前考虑到的前缀的 \(c_1 - c_0\) 的值。我们有:

\[\begin{aligned} \varnothing & \stackrel{0}{\Longrightarrow} 0 \\ & \stackrel{1}{\Longrightarrow} 1 \Longrightarrow \varnothing \end{aligned} \]

注意这里 \(1\) 可以变成 \(\varnothing\) 是因为这个 \(1\) 之后不会参与删除了,所以直接忽略它,并且让 \(c_1 - c_0\) 增加 \(1\)。

还有:

\[\begin{aligned} 0 & \stackrel{0}{\Longrightarrow} 00 \\ & \stackrel{1}{\Longrightarrow} 01 \\ 00 & \stackrel{0}{\Longrightarrow} 000 \Longrightarrow 0 \\ & \stackrel{1}{\Longrightarrow} 001 \\ 01 & \stackrel{0}{\Longrightarrow} 010 \Longrightarrow 0 \\ & \stackrel{1}{\Longrightarrow} 011 \Longrightarrow 1 \Longrightarrow \varnothing \\ 001 & \stackrel{0}{\Longrightarrow} 0010 \Longrightarrow 00 \\ & \stackrel{1}{\Longrightarrow} 0011 \Longrightarrow \varnothing \end{aligned} \]

所以自动机状态数为 \(5\)。先把当前在自动机上的结点记入状态。还要记一个当前 \(c_1 - c_0\) 的值。

发现若 \(c_1 - c_0 \ge 3\) 那么把后面的全部删了之后一定满足 \(c_1 - c_0 > 0\)。同时由于我们的策略,不会出现 \(c_1 - c_0 \le -3\) 的情况。所以 \(c_1 - c_0 \in [-2, 2]\),这样就可以记入状态了。

时间复杂度 \(O(n)\)。

code
#include <bits/stdc++.h>
#define pb emplace_back
#define fst first
#define scd second
#define mkp make_pair
#define mems(a, x) memset((a), (x), sizeof(a))

using namespace std;
typedef long long ll;
typedef double db;
typedef unsigned long long ull;
typedef long double ldb;
typedef pair<ll, ll> pii;

const int maxn = 300100;
const int mod = 1000000007;
const int ch[5][2] = {1, 0, 2, 3, 1, 4, 1, 0, 2, 0}, g[5][2] = {-1, 1, -1, 1, 1, 1, -1, 1, -1, 1};

int n, f[maxn][5][5], pw[maxn], a[maxn];
char s[maxn];

inline void upd(int &x, int y) {
	x = (x + y < mod ? x + y : x + y - mod);
}

void solve() {
	scanf("%s", s + 1);
	n = strlen(s + 1);
	pw[0] = 1;
	for (int i = 1; i <= n; ++i) {
		pw[i] = pw[i - 1] * 2 % mod;
	}
	for (int i = n; i; --i) {
		a[i] = a[i + 1] + (s[i] == '?');
	}
	f[0][2][0] = 1;
	int ans = 0;
	for (int i = 1; i <= n; ++i) {
		for (int j = 0; j <= 4; ++j) {
			for (int u = 0; u < 5; ++u) {
				if (!f[i - 1][j][u]) {
					continue;
				}
				for (int o = 0; o <= 1; ++o) {
					if (s[i] == '0' + (o ^ 1)) {
						continue;
					}
					int v = ch[u][o], t = g[u][o];
					if (j + t == 5) {
						ans = (ans + 1LL * f[i - 1][j][u] * pw[a[i + 1]]) % mod;
					} else {
						upd(f[i][j + t][v], f[i - 1][j][u]);
					}
				}
			}
		}
	}
	for (int i = 2; i <= 4; ++i) {
		for (int j = 0; j < 5; ++j) {
			upd(ans, f[n][i][j]);
		}
	}
	printf("%d\n", ans);
}

int main() {
	int T = 1;
	// scanf("%d", &T);
	while (T--) {
		solve();
	}
	return 0;
}

标签:AtCoder,typedef,stackrel,Contest,int,010,000,Grand,Longrightarrow
From: https://www.cnblogs.com/zltzlt-blog/p/18071108

相关文章

  • Dwango Programming Contest 6th D 题解
    正好测试一下专栏的题解系统。我省选寄了都怪洛谷/fn/fn/fn/fn/fn/fn/fn题解显然可以对于所有关系建有向边,显然是基环外向树森林。由于是字典序最小,因此找到最小的上一个点没有直接连向边的点一定最优。但是有时取最优会导致最后无法选完,我们考虑无法选完的情况。第一种是......
  • AtCoder Beginner Contest 344 A-G 题解
    AtCoderBeginnerContest344A-SpoilerQuestion删除两个|之间的字符Solution按照题意模拟即可Code#include<bits/stdc++.h>usingnamespacestd;intmain(){strings;cin>>s;stringp1,p2;for(inti=0;i<s.size();i++){......
  • Toyota Programming Contest 2024#3(AtCoder Beginner Contest 344)
    C先预处理出三个数组能拼出的数,存放到map中。查询的时候只需要看这个数是否出现在map里即可。时间复杂度\(O(n^3\logv+Q\logv)\),\(n\leq100\),\(\logv\)是map的时间复杂度。#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongconstintN=3e......
  • AtCoder Beginner Contest 344
    B-Delimiter难度:⭐题目大意把一个数组倒序输出;解题思路没啥好说的;神秘代码#include<bits/stdc++.h>#defineintlonglong#defineIOSios::sync_with_stdio(false);cin.tie(0);cout.tie(0);#defineendl'\n'usingnamespacestd;constintN=4e6+......
  • AtCoder Beginner Contest 344
    A-Spoiler#include<bits/stdc++.h>usingnamespacestd;usingi32=int32_t;usingi64=int64_t;usingldb=longdouble;#defineinti64usingvi=vector<int>;usingpii=pair<int,int>;constintmod=998244353;constintinf......
  • AtCoder Beginner Contest 344
    AtCoderBeginnerContest344ABCD略EInsertorErase手写链表调了这么久。。链表模板。FEarntoAdvance考虑DP,但是我们发现不是很好转移,然后我们发现\(n\le80\),我们观察一下题目的性质。如果路径确定了,那么我们肯定会在最大值的地方使劲加到终点为止。那么我们考......
  • AtCoder Beginner Contest 344
    基本情况ABCE秒了,D小细节处理出错(太久没写dp)+4。D-StringBagshttps://atcoder.jp/contests/abc344/tasks/abc344_d分组背包,但是字符串的细节要注意signedmain(){intn;std::stringT,str[110][15];intF[110][110],a[110];std::cin>>T>>n;......
  • Weekly Contest 387
    ProblemADistributeElementsIntoTwoArraysI思路按照题意模拟即可.代码classSolution{publicint[]resultArray(int[]nums){intn=nums.length;int[]ans=newint[n];int[]arr1=newint[n];int[]arr2=newint[......
  • CF contest 1935 Round 932 (Div. 2) A-D题解
    CodeforcesRound932(Div.2)A-D题解CodeforcesRound932(Div.2)绪言很菜,AB速度慢,卡在C,想DP,但是时间优化不下来,说服自己\(2\times10^3\)能过\(n^3\),D稍微简单,但是没看D,遂掉分。A.EntertainmentinMAC给你一个字符串\(s\)和一个偶整数\(n\)。你可以对它进行两种运......
  • AtCoder Regular Contest 171
    Preface小补一场ARC,D还是很有意思的但想了半天不会,鉴定为纯纯的彩笔A-NoAttacking考虑怎么放rook能使得留下来能放pawn的格子数量最多,手玩一下会发现先按照\((2,2),(4,4),(6,6),\cdots\)的顺序放,放满后再接着放\((1,1),(3,3),(5,5),\cdots\)是最优的手玩一下可以得出在放......