【补题】Codeforces 1073: Educational Round 53 (Rated for Div. 2) ABCD

版权声明:欢迎评论交流,转载请注明原作者。 https://blog.csdn.net/m0_37809890/article/details/83422771

总结

第五场爆炸cf,心情复杂

A. Diverse Substring 简单字符串

给定一个长度为n的字符串,求它的任意一个优秀子串,或输出不存在。优秀串的定义是每个字母的出现次数都不超过n/2次。

当且仅当字符串的字符全部相同时,不存在优秀子串。否则找到一个前后不相同的位置输出长度为2的子串即可。

B. Vasya and Books

模拟

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 500016, MOD = 1000000007;

int use[M];
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	int n = read();
	queue<int> st;
	for(int i=0;i<n;++i)
		st.push(read());
	for(int i=0;i<n;++i)
	{
		int val = read();
		if(use[val])
		{
			printf("0 ");
		}
		else
		{
			int cnt = 1;
			while(st.front()!=val)
			{
				use[st.front()]=1;
				st.pop();
				++cnt;
			}
			use[val] = 1;
			st.pop();
			printf("%d ",cnt );
		}
	}

    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

C. Vasya and Robot 二分

二分答案。

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline int read();
const int M = 200016, MOD = 1000000007;

int n,x,y;
char save[M];
int sumx[M],sumy[M];
bool check(int len)
{
	for(int st=1;st+len-1<=n;++st)
	{
		int ed = st+len-1;
		int px = x-sumx[st-1]-(sumx[n]-sumx[ed]);
		int py = y-sumy[st-1]-(sumy[n]-sumy[ed]);

		int xd = len-abs(px)-abs(py);
		if(xd>=0 && xd%2==0)
			return true;
	}
	return false;
}
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	n = read();
	scanf("%s",save+1);
	for(int i=1;i<=n;++i)
	{
		sumx[i] = sumx[i-1];
		sumy[i] = sumy[i-1];
		if(save[i]=='U') ++sumy[i];
		else if(save[i]=='D') --sumy[i];
		else if(save[i]=='L') --sumx[i];
		else if(save[i]=='R') ++sumx[i];
	}
	x = read(), y=read();
	if(!check(n)) return !printf("-1\n");

	int lef = 0, rig = n, ans = n;
	while(lef<=rig)
	{
		int mid = (lef+rig)>>1;
		if(check(mid))
		{
			ans = mid;
			rig = mid-1;
		}
		else
		{
			lef = mid+1;
		}
	}
	printf("%d\n",ans );

    return 0;
}


inline int read(){
    int x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

D. Berland Fair 复杂度证明

n(2e5)个糖果店围成一圈,每个糖果店都有一个售价(1e9),初始小萌有一个钱数T(1e18),初始站在第一个商店门口。小萌每次走进她面前的商店,如果钱够买一颗糖就买一颗,然后去下一家商店。问小萌最后买了多少颗糖。

方法1:线段树
首先买若干整圈直到不够买整圈,用线段树维护前缀和,查找第一个大于当前钱数的位置,将这个位置的钱数置为0,重复以上操作直到全为0为止。

没有代码,因为我不会线段树。
方法2:树状数组+二分

/* LittleFall : Hello! */
#include <bits/stdc++.h>
using namespace std; using ll = long long; inline ll read();
const int M = 500016, MOD = 1000000007;

//SimpleBinaryIndexTree.cpp 简化版树状数组
ll N,bit[M];
inline void modify(int p, ll x)
{
	for(;p<=N;p+=p&-p) bit[p]+=x;
}
inline ll sum(int p)
{
	ll res = 0;
	for(;p;p-=p&-p) res += bit[p];
	return res;
}
inline ll sum(int l, int r)
{
	return sum(r) - sum(l-1);
}

int search(ll val,int cur) //二分下一个失败位置
{
	int lef = cur, rig = cur+N/2-1, ans = rig;
	val += sum(lef-1);
	while(lef<=rig)
	{
		int mid = (lef+rig)>>1;
		if(sum(mid) > val) 
		{
			ans = mid;
			rig = mid-1;
		}
		else
			lef = mid+1;
	}
	return ans;
}
int main(void)
{
	#ifdef _LITTLEFALL_
	freopen("in.txt","r",stdin);
    #endif

	ll n=read(),T=read();
	N = 2*n;
	for(int i=1;i<=n;++i)
	{
		ll val = read();
		modify(i,val);
		modify(i+n,val);
	}

	ll ans = 0;
	stack<int> fails; fails.push(0);
	for(ll cnt = n, cur=1, amo = sum(n);cnt;--cnt)
	{
		ans += cnt * (T/amo); T %= amo;

		int fail = search(T,cur); //二分失败位置
		T -= sum(cur,fail-1);
		while(fail>n) fail-=n;
		ll val = sum(fail,fail);
		amo -= val;
		modify(fail,-val);
		modify(fail+n,-val);

		fails.push(fail);

		cur = fail+1;
		while(cur>n) cur-=n;
	}
	memset(bit,0,sizeof(bit));
	int lst=fails.top();
	while(!fails.empty())
	{
		int now = fails.top(); fails.pop();
		if(now)
		{
			modify(now,1);
			modify(now+n,1);
		}
		if(lst<now) lst+=n;
		if(lst>now) ans += sum(now+1,lst-1);
		lst = now;
	}

	printf("%I64d\n",ans);

    return 0;
}


inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}

方法3:暴力

猜你喜欢

转载自blog.csdn.net/m0_37809890/article/details/83422771