Educational Codeforces Round 110 Rated for Div. 2
大约是写了一个小时的样子。
然后就外网断连劝退了,登不上去我就看莫比乌斯去了。。。
第四题也补一下吧!
A - Fair Playoff
简单题,无讲解
为啥WA了一发,早上太迷糊了,T没初始化就给交了
#include <bits/stdc++.h>
#define int long long
using namespace std;
void solve()
{
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
int a,b,c,d;
cin>>a>>b>>c>>d;
int t1=max(a,b);
int t2=max(c,d);
if((t1>c||t1>d)&&(t2>a||t2>b)) printf("YES\n");
else printf("NO\n");
}
}
signed main()
{
int T=1;
// cin>>T;
for(int index=1;index<=T;index++)
{
solve();
}
return 0;
}
B - Array Reodering
给了一个数组,可以随便交换元素的位置。
问满足
1
<
1
≤
i
<
j
≤
n
a
n
d
g
c
d
(
a
i
,
2
∗
a
j
)
>
1
1<1≤i<j≤n \ \ \ \ \ \ \ and \ \ \ \ \ \ \ gcd(a_i,2*a_j)>1
1<1≤i<j≤n and gcd(ai,2∗aj)>1的二元组的数量
猛地一看有点难度呀。
仔细一看如果我
a
i
a_i
ai为偶数呢,我跟后面所有的都能配对呀。
直接前面全放偶数,奇数放后面暴力的搜一遍就是
a
n
s
ans
ans了
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+5;
int a[N];
int b[N];
void solve()
{
int n;
cin>>n;
int cnt=1;
int num=0;
for(int i=1;i<=n;i++)
{
cin>>a[i];
if(a[i]%2==1)
{
b[cnt++]=a[i];
}
else num++;
}
int ans = (2*n-num-1)*num/2;
for(int i=1;i<cnt;i++)
{
for(int j=i+1;j<cnt;j++)
{
if(__gcd(b[i],2*b[j])>1) ans++;
}
}
printf("%d\n",ans);
}
signed main()
{
int T=1;
cin>>T;
for(int index=1;index<=T;index++)
{
solve();
}
return 0;
}
C - Unstable String
有点跟以前的感觉不一样了。这次的第三题居然不是思维题了,也不是。
是思维题但不完全是思维题!
就是给一个序列由0、1、?组成
?既可以当1又可以当0
问这个序列的子序列满足相邻两位不一样的数量
就比如010101满足 111不满足。单个数字0和1都是满足的
怎么做呢?
问子串数量,子串长度105一看这个数据量
像这种跟区间长度,的这个数据量,求一个数量? 我的第一反应单调队列或者dp
单调队列的话,仔细想想你也没有单调性呀。而且他还有子结构性质!
dp题,蒟蒻瑟瑟发抖
如果说,我们从一个子序列开头想,我们不知道他结束的位置。这是一个很麻烦的事情。
但是如果说我们从结尾开始想呢,前面的满足条件的距离就会是他的添加这个字符的新添加的ans!
那么思路就来了,我们只要维护0和1字符在每一个字符前面满足的距离就可以了!
线性dp的基本思想在之前就总结过这里不再详述
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+5;
void solve()
{
string s;
cin>>s;
int t0=0;
int t1=0;
if(s[0]=='0') t0=1;
else if(s[0]=='1') t1=1;
else
{
t1=t0=1;
}
int ans=1;
int length=s.size();
for(int i=1;i<length;i++)
{
if(s[i]=='0')
{
t0=t1+1;
ans+=t0;
t1=0;
}
else if(s[i]=='1')
{
t1=t0+1;
ans+=t1;
t0=0;
}
else
{
swap(t0,t1);
t0++;
t1++;
ans+=max(t1,t0);
}
}
printf("%lld\n",ans);
}
signed main()
{
int T=1;
cin>>T;
for(int index=1;index<=T;index++)
{
solve();
}
return 0;
}
D - Playoff Tournament(补)
一道线段树的简单题目!正好练习一下不看板子写线段树的build
用build初始化ans数组,每次修改其中一个值,我们就每次除以二把沿路径的都修改掉就可以了!
好像还有用dp做的,但是才熟悉线段树,练习一下吧!
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int N=2e3+5;
const int maxn=1e6+10;
int n;
int ans[maxn];
char str[maxn];
char s[maxn];
void build(int rt,int l,int r)
{
if(l==r)
{
ans[rt]=1;
return;
}
int mid=(l+r)>>1;
build(rt<<1,l,mid);
build(rt<<1|1,mid+1,r);
if(s[rt]=='0')ans[rt]=ans[rt<<1|1];
if(s[rt]=='1')ans[rt]=ans[rt<<1];
if(s[rt]=='?')ans[rt]=ans[rt<<1]+ans[rt<<1|1];
}
void solve()
{
scanf("%lld%s",&n,str+1);
int len=(1<<n);
for(int i=1;i<len;i++)
{
s[i]=str[len-i];
}
build(1,1,len);
int m;
scanf("%lld",&m);
for(int i=1;i<=m;i++)
{
int x;
char op[3];
scanf("%lld%s",&x,op+1);
x=len-x;
s[x]=op[1];
while(x)
{
if(s[x]=='0')ans[x]=ans[x<<1|1];
if(s[x]=='1')ans[x]=ans[x<<1];
if(s[x]=='?')ans[x]=ans[x<<1]+ans[x<<1|1];
x>>=1;
}
cout<<ans[1]<<endl;
}
}
signed main()
{
int T=1;
//cin>>T;
for(int index=1;index<=T;index++)
{
solve();
}
return 0;
}
E - Gold Transfer(读题)
一道树上操作的题目。
看了题解说是一道倍增+交互的题目。
对交互题有点阴影------