Educational Codeforces Round 78 Rated for Div. 2
链接https://codeforces.com/contest/1278
A. Shuffle Hashing
题意:给定字符串p和h问,p是不是h的中间一串(顺序不同)
思路:给 p 排个序,在 h 中枚举一下长度为 n 的串
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2000+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t;
string p,h;
bool check(string s)
{
sort(s.begin(),s.end());
for(int i=0;i<s.size();++i)
if(s[i]!=p[i])
return false;
return true;
}
int main()
{
cin>>t;
while(t--)
{
cin>>p>>h;
sort(p.begin(),p.end());
int n=p.size();
int m=h.size();
bool ok=false;
for(int i=0;i+n-1<m;++i)
{
if(check(h.substr(i,n)))
{
ok=true;
break;
}
}
if(ok)
puts("YES");
else
puts("NO");
}
return 0;
}
B. A and B(公式)
题意:
±
1
±
2
±
3
±
4
+
⋯
+
±
x
=
n
\pm 1 \pm 2 \pm 3 \pm 4+\dots + \pm x = n
±1±2±3±4+⋯+±x=n,给定 n ,问最小的 x 的值
思路:枚举
(
1
+
i
)
i
2
\frac {(1+i)i}{2}
2(1+i)i,设 t =
(
1
+
i
)
i
2
\frac {(1+i)i}{2}
2(1+i)i 当
t
≥
n
t\ge n
t≥n 并且
(
t
−
n
)
%
2
=
=
0
(t - n) \%2==0
(t−n)%2==0的时候,
i
i
i 就是答案
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=1e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t;
ll a,b;
int main()
{
cin>>t;
while(t--)
{
cin>>a>>b;
ll x=abs(a-b);
if(x==0)
{
puts("0");
continue;
}
ll ans=1;
while(1)
{
ll t=(ans+1)*ans/2;
if(t>=x&&(t-x)%2==0)
break;
ans++;
}
cout<<ans<<"\n";
}
return 0;
}
C. Berry Jam(折半枚举)
题意:从 n 和 n + 1 的位置,往两边清空,问至少清空几个瓶子,使得蓝莓和红莓的瓶子数量相同
思路:红莓的瓶子设为 1 ,蓝莓的瓶子设为 -1 。就是求一个最小的数量,使得和为
0
0
0
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int maxn=2e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int t,n;
ll sum[maxn];
map<int,int> m;
int main()
{
cin>>t;
while(t--)
{
m.clear();
memset(sum,0,sizeof(sum));
cin>>n;
m[0]=0;//全部都取
for(int i=1;i<=2*n;++i)
{
int x;
scanf("%d",&x);
sum[i]=sum[i-1]+(x==1?1:-1);
if(i<=n)
m[sum[i]]=i;
}
int ans=inf;
for(int i=n;i<=2*n;++i)
{
auto x=m.find(sum[i]-sum[2*n]);
if(x!=m.end())
ans=min(ans,i-x->second);
}
cout<<ans<<"\n";
}
return 0;
}
D. Segment Tree(set+并查集)
题意:两个区间相交且不内嵌的时候,可以连一条边,问最后是否可以连成一棵树?
思路:一棵树只有n-1条边。用并查集维护连边,用map查找加边。
- 加入边的时候,如果同父亲,就已经连过边了,再连就不止n-1条边了
#include <bits/stdc++.h>
#define fi first
#define se second
#define ll long long
using namespace std;
const int maxn=5e5+5,maxm=1e5+5;
const int mod=1e9+7,inf=0x7f7f7f7f;
int n;
pair<int,int> seg[maxn];
map<int,int> m;
int p[maxn];
int finds(int x)
{
return x==p[x]?x:p[x]=finds(p[x]);
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;++i)
scanf("%d%d",&seg[i].fi,&seg[i].se),p[i]=i;
sort(seg+1,seg+1+n);
int cnt=0;
for(int i=1;i<=n;++i)
{
auto it=m.lower_bound(seg[i].fi);
while(it!=m.end()&&seg[i].se>it->fi)
{
int fx=finds(i),fy=finds(it->se);
if(fx==fy||cnt>=n)
{
puts("NO");
return 0;
}
else
{
cnt++;
p[fx]=fy;
}
it++;
}
m[seg[i].se]=i;
}
if(cnt==n-1)
puts("YES");
else
puts("NO");
return 0;
}