版权声明:欢迎评论交流,转载请注明原作者。 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:暴力