首页 > 其他分享 >AtCoder Beginner Contest 380 A - E

AtCoder Beginner Contest 380 A - E

时间:2024-11-17 14:45:25浏览次数:1  
标签:AtCoder rp Beginner 10 int mid cin 380 define

link

赛时是 ABC,D 一眼要找规律,跳了,E 题思路想了接近半个小时,然后发现假了,最后没调出来,

问一下 dalao 发现其实很简单维护。。。基础线段树没切掉,哎呦

不过发现比赛打多了,理解速度和手速都有些提高,幸好前三题秒掉了,要不然 rating 又会是一坨


A - 123233

B - Hurdle Parsing

C - Move Segment

D - Strange Mirroring

一道简单递归。

发现字符串是成倍增长的,显然考虑找规律,

手摸一下会发现,要找的字母其实是由之前的 相反的 字母转换过来的,而这条转换链也很有规律,

比如样例 1,找 30 位置,理解为 2 ^ 5 - 2,是由 14(2 ^ 4 - 2)大小写取反转换,又由 6(2 ^ 3 - 2)...... 最后将规模转化为原长字符串中。

显然递归是 \(\log\) 的,还有,每次找位置的规模是随递归减小的,所以达不到 \(\log^2n\) 吧

code
#include <bits/stdc++.h>
#define re register int 
#define int long long

using namespace std;
const int N = 2e5 + 10;

string s;
int q;

inline char change(char x)
{
	if ('a' <= x && x <= 'z') return x - 'a' + 'A';
	else return x - 'A' + 'a';
}

inline char find(int x, bool flag)
{
	if (x <= s.size())
	{
		if (flag) return change(s[x - 1]);
		else return s[x - 1];
	}
	int k = s.size();
	while ((k << 1ll) < x) k <<= 1ll;
	find(x - k, !flag);
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> s;
	cin >> q;
	while (q --)
	{
		int x; cin >> x;
		cout << find(x, false) << ' ';
	}
	cout << '\n';
	return 0;
}

E - 1D Bucket Tool

维护序列的全相等联通块,感觉是个很常见的东西,确实做法很多,set,dsu 都可以,

原谅我只想到复杂度更劣的 线段树 + 二分 qwq

一眼看上去,是个很可以用线段树维护的 ds 题

区间修改很简单

主要是如何维护,给定一个位置,找该位置的颜色的最大连通块,还要是 \(\log\) 级别的时间

一开始是想倍增跳,但是发现不好维护 连续相同

最后只能是从线段树直接维护的角度想,突然注意到,找连通块的左右界,是可以二分的。这是显然的,可以简单考虑为区间长度越长,越更可能 不连续相同,也就是说如果长度更短的区间都不能连续,那么更长的不可能更优

然后考虑区间连续相同是不是等价于 \(\bigcup\limits_{i = l}^r a_i = a_k~(k\in[l, r])\) 呢?然后 wa 了一大堆。。。

赛后发现随便举出反例 10 & 11 & 10 = 10

其实是可以直接维护这个逻辑的,,,子区间相同或否,pushup 维护一个标志值就可以了。最后区间查询,发现数据范围比较小,直接开个颜色的桶就可以了。

复杂度 \(O(n\log^2n)\)

code
#include <bits/stdc++.h>
#define re register int 
#define lp p * 2
#define rp p * 2 + 1
#define int long long

using namespace std;
typedef pair<int, int> PII;
const int N = 5e5 + 10;

struct Tree { int l, r, sum, tag, flag; } t[N << 2];
int n, q, num[N];

inline void push_up(int p)
{
	t[p].sum = t[lp].sum + t[rp].sum;
	t[p].flag = ((t[lp].flag == t[rp].flag && t[lp].flag) ? t[lp].flag : 0);
}

inline void push_down(int p)
{
	if (t[p].tag)
	{
		t[lp].sum = (t[lp].r - t[lp].l + 1) * t[p].tag;
		t[rp].sum = (t[rp].r - t[rp].l + 1) * t[p].tag;
		t[lp].flag = t[rp].flag = t[p].tag;
		t[lp].tag = t[p].tag;
		t[rp].tag = t[p].tag;
		t[p].tag = 0;
	}
}

inline void build(int p, int l, int r)
{
	t[p].l = l, t[p].r = r;
	if (l == r)
	{
		t[p].sum = t[p].flag = l;
		return;
	}
	int mid = (l + r) >> 1;
	build(lp, l, mid); build(rp, mid + 1, r);
	push_up(p);
}

inline void update(int p, int l, int r, int k)
{
	if (l <= t[p].l && t[p].r <= r)
	{
		t[p].sum = (t[p].r - t[p].l + 1) * k;
		t[p].flag = k;
		t[p].tag = k;
		return;
	}
	push_down(p);
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) update(lp, l, r, k);
	if (r > mid) update(rp, l, r, k);
	push_up(p);
}

inline int query(int p, int l, int r)
{
	if (l <= t[p].l && t[p].r <= r) return t[p].sum;
	push_down(p);
	int res = 0;
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) res += query(lp, l, r);
	if (r > mid) res += query(rp, l, r);
	
	return res;
}

inline bool ask(int p, int l, int r, int k)
{
	if (l <= t[p].l && t[p].r <= r)
	{
		if (t[p].flag != k) return false;
		return true;
	}
	push_down(p);
	bool res = true;
	int mid = (t[p].l + t[p].r) >> 1;
	if (l <= mid) res &= ask(lp, l, r, k);
	if (r >mid) res &= ask(rp, l, r, k);
	
	return res;
}

inline PII search(int x)
{
	int a = query(1, x, x);	
	int L, R;
	
	int l = 1, r = x;
	while (l < r)
	{
		int mid = (l + r) >> 1;
		if (ask(1, mid, x, a)) r = mid; 
		else l = mid + 1;
	}
	L = l;
	
	l = x, r = n;
	while (l < r)
	{
		int mid = (l + r + 1) >> 1;
		if (ask(1, x, mid, a)) l = mid;
		else r = mid - 1;
	}
	R = l;
	
	return {L, R};
}

signed main()
{
	ios::sync_with_stdio(false);
	cin.tie(0); cout.tie(0);
	
	cin >> n >> q;
	build(1, 1, n);	
	for (re i = 1; i <= n; i ++) num[i] = 1;
	
	while (q --)
	{
		int op, x, y; cin >> op;
		if (op == 1)
		{
			cin >> x >> y;
			PII k = search(x); int l = k.first, r = k.second;
			
			num[query(1, x, x)] -= (r - l + 1);
			update(1, l, r, y);	
			num[y] += (r - l + 1);
			
		}
		else 
		{
			cin >> x;
			cout << num[x] << '\n';
		}
	}
	
	return 0;
}

标签:AtCoder,rp,Beginner,10,int,mid,cin,380,define
From: https://www.cnblogs.com/wenzieee/p/18550545

相关文章

  • AtCoder Beginner Contest 380
    省流版A.计数判断即可B.计数统计即可C.模拟即可D.注意到字符串是左右大小写镜像,从长度大往小依次考虑实际所处的位置,维护镜像次数集合E.并查集维护连通性,并尝试与左右俩格子合并即可F.博弈\(dp\),状态数只有\(5e5\),直接记忆化搜索即可G.枚举打乱起始位置,全排列分......
  • Atcoder 11.17
    这是11.17号的题单4.第四题是字符串的问题,只需要找到规律即可,对于每个查询k[i],首先计算a和aa:a是(k[i]-1)//ls,即k[i]-1除以字符串长度ls的商。这相当于确定k[i]在重复字符串中属于第几个完整的字符串块。aa是bin(a).count("1")%2,即a的二进制表示中"1"......
  • AtCoder Beginner Contest 380
    A-123233题意给个\(6\)位数,判断是否是\(1\)个\(1\),\(2\)个\(2\),\(3\)个\(3\)。思路模拟。代码点击查看代码#include<bits/stdc++.h>usingnamespacestd;#defineintlonglongtypedefpair<int,int>pii;constintmxn=1e6+5;voidsolve(){ s......
  • ABC380题解(F&G)
    ABC380F.ExchangeGame因为\(n+m+k\leq12\),考虑状压dp,设\(f(x,s1,s2,s3)\)表示先手,后手,桌子上的牌分别是哪一些,这有\(O(3^n)\)种状态。然后只要枚举出哪一张即可,有\(f(s1,s2,s3)\tof(s2,s1-i+j,s3+i-j)(i\ins1,j\ins3,a_j<a_i)\)\(f(s1,s2,s3)\tof(s2,s1-i,s3+i......
  • ABC380
    Clink点击查看代码#include<bits/stdc++.h>usingnamespacestd;intn,k;chars[500005];intqr,dg,dl,dr;signedmain(){ cin>>n>>k>>s+1; intlx=1,rx=0,op=0,gs=0; for(inti=1;i<=n&&op<=k;++......
  • AtCoder Grand Contests 杂做
    感觉AGC003及以前的题做了大部分,所以从AGC004开始,选一些我觉得合适的题做。AGC004E-*3200一直在往静态的几何(或者代数)限制想,结果没想到可以动态规划。为了更加直观可以看作出口在移动,然后到过的点加分,某些出界的点就被ban掉了。我们可以直接考虑定义\(f_{l,r,u,d}\)......
  • Toyota Programming Contest 2024#11(AtCoder Beginner Contest 379)题解总结
    AtCoderBeginnerContest379Rated:\(770\)A-Cyclic简单模拟。B-Strawberries字符串模拟,substr函数秒了C-Repeating中等模拟。思路:判断是否合法很简单,重点在计算花费。假设我们是\(0\)号点有\(N\)个棋子,然后移动到每个点上,显然花费为\(\frac{N(N+1)}{......
  • AtCoder Beginner Contest 379
    省流版A.模拟即可B.贪心,有\(k\)个就吃,模拟即可C.维护已经有棋子的格子,有多个棋子往右推,代价等差数列求和,模拟即可D.注意到植物高度=当前天-种植天,维护植物的种植天然后二分找对应高度的植物即可E.考虑最终答案每一个数位的值,然后处理进位即可F.单调栈处理建筑\(r\)......
  • Atcoder ABC 216 G 01Sequence 题解 [ 蓝 ] [ 差分约束 ]
    01Sequence:比较板的差分约束,但有一个很妙的转化。朴素差分约束设\(x_i\)表示第\(i\)位的前缀和。我们要最小化\(1\)的个数,就要求最小解,就要求最长路。因为约束条件都是大于等于号,所以求最长路才能满足所有条件。求最大解也是同理。我们可以对于每一个条件,列出如下不等式......
  • Atcoder Beginner Contest 379 (A-F)
    AtcoderBeginnerContest379(A-F)题目链接A-Cyclic#include<bits/stdc++.h>usingnamespacestd;usingi64=longlong;voidShowball(){chara,b,c;cin>>a>>b>>c;cout<<b<<c<<a<<""<......